JavaScript学习之路--执行环境及作用域链解析

来源:互联网 发布:淘宝如何申请小二介入 编辑:程序博客网 时间:2024/05/16 12:51

执行环境(execution context)

  在JavaScript中,执行环境是最为重要的一个概念。执行环境定义了变量或者函数有权访问的数据,通过合一特性决定了它们各自的行为。
  每一个执行环境都有一个与之关联的变量对象(variable object),这个对象保存了环境中所定义的所有变量和函数,这个对象是代码曾层无法访问到的,但解析器在处理数据时会在后台使用它。
  全局执行环境是执行环境最外围的一个执行环境。根据ECMAScript实现所在的宿主环境的不同,表示的执行环境的对象也不一样,所以在我们常用的Web浏览器中,全局执行环境被认为是Window对象。由此可知,所有全局变量和函数都是作为window对象的属性和方法创建的。
  每个函数都有自己的执行环境。当执行流进入一个函数时,函数的环境会被压入一个环境栈中,在函数执行完毕后,栈将其环境弹出,将控制权移交给之前的环境。

作用域链(scope chain)

  当代码在一个环境中执行时,首先会创建变量对象的一个作用域链。作用域链的用途就是保证对执行环境有权访问所有变量和函数的有序访问。
  解释一下“有权访问”,抛开全局变量与局部变量的概念不说,简单来说,每个环境都有自己的变量与函数,在作用域链的搜索过程中,是自底向上搜索,内部包含外部的。在作用域链的最前端,始终为当前执行代码所在的执行环境,作用域链中的下一个变量对象则来自包含(外部)环境,再下一个来自下一个包含环境,最后一个变量对象始终都是全局执行环境的变量对象。
  那么有权访问就很好理解了,就是说内部的可以访问到所有外部的变量,但是外部的不一定能够访问到内部的变量对象。
  现在再说一下标识符解析,这个过程就是沿着作用域链一级一级地搜索标识符的过程。搜索过程始终从作用域链的前端开始,逐级的向外搜索,知道找到标识符为止。

var color = "blue";function changeColor(){    if(color === "blue"){        color = "red";    }else{        color = "blue";    }}changeColor();alert("color is"+color);//red

  在这个简单例子中,函数changeColor()的作用域包含两个对象:它自己的变量对象和全局环境变量对象。之所以可以在函数内部访问变量color,就是因为在作用域链中能找到它。
  再看一个稍微复杂点的例子:

var color = "blue";function changeColor(){    var anotherColor = "red";        function swapColor(){            var tempColor = anotherColor;            anotherColor = color;            color = tempColor;            //可以访问color,anotherColor,tempColor    }    swapColor();    //可以访问color,aotherColor,不能访问到tempColor}changeColor();//只能访问到color

  在以上代码中,涉及到了三个执行环境:全局环境、changeColor()函数的局部环境、swapColor()函数的局部环境。在全局环境中有一个变量color和一个函数changeColor()。在changeColor()局部环境中,有一个名为anotherColor的变量和swapColor()的函数。在swapColor()的局部环境中,有一个变量tempColor,该变量只能在这个执行环境中访问到。无论是全局环境还是函数changeColor()函数的环境都无法访问到tempColor变量。然而,在swapColor()函数中,可以访问到其他两个环境中的所有变量。
  综上,内部环境可以通过作用域链访问到所有外部环境,但外部环境不能访问内部环境中的任何变量和函数。
  这些环境之间的联系是线性的、有次序的。每个环境可以向上搜索作用域链,以查询变量和函数名,担任何环境不能通过向下搜索作用域链进入另一个执行环境。

注意

  JavaScript中没有块级作用域。在其他类C语言中,由花括号封闭的区域都有自己的作用域,也就是它自己的执行环境,因而支持,根据条件来定义变量。
  来看如下代码:
  

if(true){    var color = "blue";}alert(color);

  这里是在一个 if 语句中定义了一个变量color。如果在C/C++/java中,color会在执行完毕 if 语句后被销毁。但在JavaScript中,if 语句中声明的变量会被添加到当前执行环境中,尤其在使用for语句时,更加明显,例如:
  

for(var i = 0;i < 5;i++){    dosomething(i);}alert(i);//i=5

  对于JavaScript来说,由for语句创建的 i 变量即使在for循环结束后也依旧存在于循环外部的执行环境中。
  

0 0