javascript中的作用域链

homeros    前端    999+ 次    2017-12-12 17:21:52


Javascript是基于词法作用域的语言:通过阅读包含变量定义在内的数行源代码就能知道变量的作用域。全局变量在程序中始终有定义,局部变量在声明它的函数体内以及所嵌套的函数内始终有定义。

 

首先,有几个概念是需要先弄明白的。

执行上下文

 


什么是”上下文“?在计算机领域,这个名词比较抽象,简单理解,就是程序在执行的时候,程序当前的状态,一般可以简单理解成”当前能直接或间接访问到的程序变量“。

 

javascript在执行的时候,可以分成 1)顶层代码,和 2) 函数内代码。顶层代码的含义就是不包含在任意函数定义内的代码。

顶层代码的执行上下文,可以认为就是全局对象(glabal),在浏览器中就是window对象。

至于函数内的代码,只有执行的时候,才会有”执行上下文“。

可以简单将函数的执行上下文理解成类似下面的对象:

 

var executionContext = {    activeObject: {...}, // 活动对象。什么是活动对象?    scopeChain: [activeObject, ...], // 作用域链    this: {...} // this关键字};

 

当一个函数执行的时候,会首先构造一个执行上下文,步骤如下:

a. 创建活动对象

b. 构造作用域链

c. 构造this对象

下面详细说明各个步骤:

活动对象

我们可以把参数、局部变量都看作是一个自定义实现的对象的属性,这个自定义的对象我们称为”活动对象“。

作用域链

为说明方便,我们把顶层的代码看做运行在一个不可见的、全局的匿名函数里。

作用域链是不能脱离函数来说明的,它跟函数紧密相连,只有与函数一块时,作用域链才有意义。

函数:

1) 在定义的时候,每个函数对象都有一个内部的属性:[[Scope]],这个属性的值,就是当前正在执行的函数的作用域链

2) 在执行的时候,会构造一个活动对象,并且将活动对象和[[Scope]]合并在一起组成作用域链(scope chain),而活动对象在作用域链的最前面

假设我们在顶层代码定义了函数:

 

function add(num1, num2) {    return num1 + num2;}

 

那在定义的时候,函数add对象就有一个内部属性[[Scope]]了,它是一个数组或链表,只有一个元素,指向全局对象。如图:

当调用add方法的时候,会构造一个执行上下文(execution context),上下文包含了scopeChain属性,它实际上是活动对象和add.[[Scope]]的合并,如下图:

var Total = add(5, 10);

事实上,我们可以把变量名的解析看作是从作用域链中,从头到尾遍历作用域链中的对象,看这些对象中有没有同名的属性。

with语句

了解了作用域链的概念后,就很容易理解with语句的含义:with语句,就是简单粗暴地将一个对象插入作用域链的头部。

使用局部变量提高性能

在jquery源代码中,可以看到有类似的代码:

 

(function(window) {    var preferredDoc = window.document; // 这里直接使用window的局部变量,省了一次查上一个的作用域链对象      // 底下有许多地方直接用到了preferredDoc,这就避免了遍历全部的作用域链对象})(window);

 

闭包

作用域链理解透了,闭包也可以顺利理解。

什么是闭包?函数体的局部变量可以保存在它的作用域链中。

当函数有嵌套时,我们约定:被嵌套的函数叫 内部函数(inner function),外层的函数称为外部函数(outer function)。

那么,当inner function运行的时候,inner function的作用域链,也会包含outer function的作用域链:inner function的作用域链=inner function的活动对象+outer function的作用域链。

这种情况比较神奇,尤其在inner function被保存在outer function之外的某个变量或属性时,会发生一些神奇的现象。

function outer() {
    var foo = 1;

    function inner() {
        foo++;
        alert(foo);
    }

    return inner;
}

var f = outer();
f();
f();
var k = outer();
k();

上一篇: COOKIE详解

下一篇: Javascript中的异步编程

最新评论

暂无评论

热门文章

最新评论

网站数据

网站文章数:481

今日UV/PV/IP:18/21/17

昨日UV/PV/IP:26/29 /25

TOP