JavaScript作用域链实例详解

跟其他语言一样,变量和函数的作用域揭示了这些变量和函数的搜索路径。对于JavaScript而言,理解作用域更加重要,因为在JavaScript中,作用域可以用来确定this的值,并且JavaScript有闭包,闭包是可以访问外部环境的作用域的。
每一个JavaScript的函数都是Function对象的一个实例,Function对象有一个内部属性[[Scope]],这个属性只能被JavaScript的引擎访问。通过[[Scope]]属性可以访问函数的作用域链,从而可以搜索变量和函数,判断变量和函数位于作用域链中的哪一个活动对象中。

简单的作用域链

当一个函数被创建的时候,因为函数是Function对象的一个实例,因此也会有[[Scope]]这个内部属性,Scope属性指向一个作用域链,作用域链中默认至少包含一个全局对象变量。

function compare(value1, value2){ if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } } var result = compare(5, 10);

以上代码先定义了一个compare()函数,然后在全局作用域中调用了这个函数。 在创建compare()函数的时候,该函数的作用域链如下图所示:

JavaScript作用域链实例详解

当compare()函数在全局作用域中被调用执行的时候,JavaScript引擎会创建一个运行时上下文(execution context)的内部对象,一个运行时上下文定义了一个函数执行时的环境。函数诶次执行时的运行时上下文都是不同的,因此多次调用就会导致多个运行时上下文的创建与销毁。

每个运行时上下文都有自己的作用域链,用于变量和函数这些标识符的解析。

运行时上下文在函数调用执行时被创建,在函数执行完毕的时候被销毁。在运行时上下文创建的时候,首先会复制该被调用函数的[[Scope]]属性中的对象,然后一个活动对象(作为变量对象使用)会被创建并推入运行时上下文作用域链的前端。对于这个例子中compare()函数的运行时上下文而言,其作用域链包含两个变量对象:compare()的活动对象(activation object of compare())与全局变量对象(global object)。

对于简单的作用域链,就是这样了,但是有闭包的情况会有所不同。

JavaScript作用域链实例详解

闭包的作用域链

//step1: define createComparisonFunction function createComparisonFunction(propertyName){ return function(object1, object2){ var value1 = object1[propertyName]; var value2 = object2[propertyName]; if (value1 < value2) { return -1; } else if (value1 > value2) { return 1; } else { return 0; } }; } //step2: call createComparisonFunction var compare = createComparisonFunction("name"); //step3: call compare var result = compare({name: "Nicholas"}, {name: "Gerg"}); //step4: dereference closure for recycle memory compare = null;

我们分下列几个步骤来图解作用域链:

step1: 定义createComparisonFunction;

JavaScript作用域链实例详解

在创建createComparisonFunction函数之后,createComparisonFunction可以被调用了,因此一个createComparisonFunction的Function对象被保留下来;
此时内存中保留对象:

1. Global Object

2. createComparisonFunction对象 & Scope Chain

step2: 执行createComparisonFunction;

JavaScript作用域链实例详解

在执行createComparisonFunction的过程中,首先会创建createComparisonFunction的运行时上下文对象 + ScopeChain + 活动对象,其次会创建一个闭包(匿名函数),
函数执行时内存中保留对象:

1. Global Object
2. createComparisonFunction的Function对象 + Scope Chain
3. createComparisonFunction的运行时上下文对象 + Scope Chain
4. createComparisonFunction的活动对象
5. Closure(anonymous)的Function对象 + Scope Chain

在执行完createComparisonFunction之后,createComparisonFunction的运行时上下文对象+ScopeChain会被销毁,但是createComparisonFunction的活动对象因为被Closure(anonymous)对象的ScopeChain所引用,因此不会被销毁。

函数执行完内存中保留对象:

1. Global Object
2. createComparisonFunction的Function对象 + Scope Chain
3. Closure(anonymous)的Function对象 + Scope Chain
4. createComparisonFunction的活动对象

对比step1, step2在执行完之后,增加了两个对象:

1. Closure(anonymous)的Function对象 + Scope Chain
2. createComparisonFunction的活动对象

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:http://www.heiqu.com/046bca97336870362e5db5feb7c79132.html