关于Javascript作用域及作用域链的总结

本文是根据以下文章以及《Javascript高级程序设计(第三版)》第四章相关内容总结的。

1、Javascript作用域原理,地址:http://www.laruence.com/2009/05/28/863.html

2、JavaScript 开发进阶:理解 JavaScript 作用域和作用域链,地址:http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html

在介绍有关作用域的内容之前,先来介绍一下Javascript中的预编译。

Javascript中的预编译

这里说的Javascript中的预编译,就是指函数声明提升和变量提升。

在JS引擎执行每一段(在html页面中,一个script元素就是一段)JS代码之前,都会首先处理var关键字和函数定义式。

先说函数定义式,有两种,一种函数声明,一种函数表达式:

 1 <script>
 2 alert(func);//function func() {alert(‘something‘);}
 3 alert(thank);//undefined
 4 //这是一个函数声明
 5 function func() {
 6     alert(‘something‘);
 7 }
 8
 9 //这是一个函数表达式
10 var thank = function() {
11     alert(‘nothing‘);
12 };
13 </script>

alert语句都在两个函数定义式前面,alert(func);这一句输出了完整的func函数,alert(thank);输出undefined,说明函数声明被提升了,函数表达式没有被提升,这就是两者的区别。至于为什么,下面继续说变量提升。

变量有全局变量和局部变量,不管是哪种变量都会被提升,但提升的高度不一样。全局变量提升到全局的执行环境(这里的执行环境可以理解成作用域,活动对象,还可以理解成变量对像,都一个意思,包括下面也是)中,局部变量提升到局部的执行环境中。在变量被提升后他是没有值的,即为undefined,仅仅是一个名字,只有当代码执行到给变量赋值的语句时,它才真正有了值。

对于局部变量的提升是这么一个过程,这个过程是函数作用域链创建过程中的一部分:函数在调用,但是其中代码还没有执行之前,首先会创建一个活动对象,然后搜寻这个函数中的局部变量定义和函数定义,将变量名和函数名都作为这个活动对象的同名属性。对于局部变量定义,变量的值会在真正执行到赋值语句时才会计算,此时只是简单的赋值为undefined。

不使用var关键词和直接在全局环境中声明的变量都是全局变量,全局变量会被提升到全局的window活动对象中,但此时这些变量也是没有值的,只有执行到赋值语句时,它们的值才会被计算。

此时就可以解释为什么函数表达式没有被提升了。函数表达式是把一个匿名函数赋值给一个变量,实际上是把那个变量提升了,变量提升之后它的值为undefined。

JavaScript的作用域

《Javascript高级程序设计(第三版)》第四章中在引出作用域内容前先介绍了一个执行环境的概念,然后又说变量对像,然后又是活动对象。说了一大堆把人都绕晕了。我的理解是把执行环境就理解成作用域,作用域还不够具体,把它具体到代码层面,它就是一个对象,给这个对象起个名字叫变量对象,执行环境中的所有变量声明和函数声明都是这个变量对象的同名属性。执行环境有全局和局部之分,那么这个变量对象也有全局与局部之分,把这些全局的和局部的变量对象按照顺序排列起来就形成了作用域链,作用域链的最前端就是上文讲的函数调用时创建的那个活动对象,这个活动对象也是一个变量对象。

函数的作用域链在其声明的时候就已经开始创建了,而不是被调用的时候才开始的。

具体过程是:

当一个函数创建后,它的内部属性[[Scope]]会指向创建此函数的那个执行环境的变量对象,并把这个变量对象添加到其作用域链中。(函数的的内部属性[[Scope]]会最终指向全局环境window的变量对象,换句话说,全局对象的变量对象始终是作用域链的最后一个对象。)

当这个函数被调用时,会创建一个“运行期上下文(execution context)”,运行期上下文定义了函数执行时的环境,与这个环境相对应的是一个活动对象,该活动对象包含了函数的所有局部变量、命名参数、参数集合(arguments)以及this,然后此对象会被推入作用域链的前端,当运行期上下文被销毁,活动对象也随之销毁。

下面通过例子分析作用域链。

 1 <script>
 2 var a = 1;
 3 function func() {
 4    var b = 2;
 5    function test() {
 6       var c = b;
 7       b = a;
 8       a = c;
 9    }
10    test();
11 }
12 func();
13 alert(a);//2
14 </script>

当函数func创建完成时,他的作用域链:

[[scope chain]] = [
{
    window call object
}
]

当函数func调用时,他的作用域链:

[[scope chain]] = [
{
    b: undefined,
    test: function test() {
          var c = b;
          b = a;
          a = c;
    }
},
{
    a: 1
}
]

当test函数创建时,他的作用域链:

[[scope chain]] = [
{
    b: undefined,
    test: function test() {
          var c = b;
          b = a;
          a = c;
    }
},
{
   a: 1
} ]

当test函数调用时,他的作用域链:

[[scope chain]] = [
{
    c: undefined
},
{
    b: 2,
    test: function test() {
          var c = b;
          b = a;
          a = c;
    }
},
{
    a: 1
}
]

不知道这个例子的作用域链分析的正确不正确,如有不正确请看到的大侠们批评指正。

理解了函数声明提升和变量声明提升,以及知道作用域链的创建过程,对于理解JavaScript中函数的作用域有很大帮助,反正我是这么觉得。

时间: 2024-12-26 17:10:13

关于Javascript作用域及作用域链的总结的相关文章

javascript篇-----函数作用域,函数作用域链和声明提前

在一些类似C语言的编程语言中,花括号内的每一段代码都具有各自的作用域,而且变量在声明它们的代码段之外是不可见的(也就是我们不能在代码段外直接访问代码段内声明的变量),我们称之为块级作用域,然而,不同于这类型的编程语言,javascript是没有块级作用域.取而代之的,javascript使用的是块级作用域:变量在声明它们的函数体以及这个函数体嵌套的任意函数体内都是有定义的. 在如下的所示的代码中,在不同位置定义了变量 i . j 和 k ,它们都在同一个作用域内——这三个变量在函数体内均是有定义

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. JavaScript作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1.  全局作用域(Global S

JavaScript作用域和作用域链

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链 来源:梦想天空  http://www.cnblogs.com/lhb25/archive/2011/09/06/javascript-scope-chain.html 作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. Java

javascript学习中自己对作用域和作用域链理解

在javascript学习中作用域和作用域链还是相对难理解些,下面我关于javascript作用域和作用域链做一下详细介绍,给各位初学者答疑解惑. 首先我们介绍一下什么是作用域?  从字面上理解就是起作用的区域.   作用域主要有两种作用域:      1.块级作用域(js 不支持):主要用于C系列语言中,例如:Java Object-c/Swift(苹果开发语言).C++/C#.在此不做过多说明.      2.词法作用域  一个变量的作用范围,在代码写出来的那一刻就定下来了,不会根据代码的运

JavaScript概念总结:作用域、闭包、对象与原型链

1 JavaScript变量作用域 1.1 函数作用域 没有块作用域:即作用域不是以{}包围的,其作用域完成由函数来决定,因而if /for等语句中的花括号不是独立的作用域. 如前述,JS的在函数中定义的局部变量只对这个函数内部可见,称之谓函数作用域. 嵌套作用域变量搜索规则:当在函数中引用一个变量时,JS会搜索当前函数作用域,如果没有找到则搜索其上层作用域,一直到全局作用域. [javascript] view plain copy print? var  value = 'global';

JavaScript之作用域与作用域链

今天是2016的第一天,我们得扬帆起航踏上新的征程了.此篇阐述JavaScript中很重要的几个概念:作用域与作用域链及相关知识点. 我们先从变量与作用域的行为关系开始讨论. 变量作用域 JavaScript中,变量有全局变量及局部变量之分,而能定义变量作用域的语块只有函数.与局部变量有关的一种有趣特性,在此处不得不谈--变量提升. 变量提升 变量提升为何物? JavaScript的变量声明会被提升到它们所在函数的顶部,而初始化仍旧在原来的地方.JavaScript引擎并没有重写代码:每次调用函

JavaScript作用域及作用域链详解、声明提升

相信大家在入门JavaScript这门语言时对作用域.作用域链.变量声明提升这些概念肯定会稀里糊涂,下面就来说说这几个 Javascript 作用域 在 Javascript 中,只有局部作用域和全局作用域.而只有函数可以创建局部作用域,像 if,for 或者 while 这种块语句是没办法创建作用域的. (当然 ES6 提供了 let 关键字可以创建块作用域.) Javascript 的这种特性导致 for 循环里面创建闭包时会产生让人意想不到的结果.比如下面这个例子: var i = 20;

(转)JavaScript 开发进阶:理解 JavaScript 作用域和作用域链

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. JavaScript作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 全局作用域(Global Scope

JavaScript 开发进阶:理解 JavaScript 作用域和作用域链(转载 学习中。。。)

作用域是JavaScript最重要的概念之一,想要学好JavaScript就需要理解JavaScript作用域和作用域链的工作原理.今天这篇文章对JavaScript作用域和作用域链作简单的介绍,希望能帮助大家更好的学习JavaScript. JavaScript作用域 任何程序设计语言都有作用域的概念,简单的说,作用域就是变量与函数的可访问范围,即作用域控制着变量与函数的可见性和生命周期.在JavaScript中,变量的作用域有全局作用域和局部作用域两种. 1.  全局作用域(Global S