本文实例讲述了JavaScript闭包与作用域链。分享给大家供大家参考,具体如下:
闭包定义
闭包指的是有权访问另一个函数作用域中的变量的函数。创建闭包的常见方式,就是在一个函数A内部创建另一个函数B,那么函数B就是一个闭包,可以访问函数A作用域中的所有变量。
JavaScript的闭包与作用域链密不可分,因此本文可以和JavaScript的作用域链相对照分析,一定可以对JavaScript的闭包和作用域链有更深的理解。
下面我们仍然以createComparisonFunction为例进行闭包的分析。
//step1: define createComparisonFunctionfunction 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 createComparisonFunctionvar compareName = createComparisonFunction("name");var compareAge = createComparisonFunction("age");//step3: call comparevar object1 = { name : "Nicholas", age : 25};var object2 = { name : "Greg", age : 27};var result1 = compareName(object1, object2); // 1var result2 = compareAge(object1, object2); // -1//step4: dereference closure for recycle memorycompareName = null;compareAge = null;
在这个例子中,匿名函数function(object1, object2)是一个闭包,能访问createComparisonFunction作用域里的所有变量,自然也包含propertyName属性, 因为propertyName参数的不同,导致比较的属性也有所不同,从而函数执行结果也有不同。
闭包与变量
从JavaScript的作用域链中,我们了解到JavaScript是通过作用域链来确定函数执行环境的作用域的,这种机制会引出一个值得注意的副作用,即闭包只能取得包含函数中任何变量的最后一个值。闭包是通过引用外部函数的活动对象来访问该活动对象中的所有变量,因此在外部函数执行过程中,这些变量的值可能会变化,但是在外部函数执行完毕之后,外部函数的活动对象便不会再改变,因此在执行闭包的时候,闭包通过作用域链访问到外部函数的活动对象中的所有变量都只可能是在外部函数执行完毕之后,外部函数的活动对象中最后所保存的值。我们通过一个例子来说明这种副作用。
function createFunctions(){ var result = new Array(); for (var i = 0; i < 10; i++){ result[i] = function(){ return i; }; } return result;}var functions = createFunctions();for(var i = 0; i < functions.length; i++){ console.log(functions[i]());}
输出的结果是
10 10 10 10 10 10 10 10 10 10
从表面上看,似乎每个函数都应该返回自己的索引值,但实际上,每个函数都返回10。因为每个函数的作用域链中都保存着createFunctions函数的活动对象,所以他们引用的都是这个createFunctions函数的活动对象中的变量i,在createFunctions函数返回之后,变量i的值是10,此时每个函数都引用着保存变量i的同一个变量对象,所以每个函数内部i的值都是10。
新闻热点
疑难解答