您的当前位置:首页JavaScript闭包与作用域链实例分析

JavaScript闭包与作用域链实例分析

2020-11-27 来源:乌哈旅游

从表面上看,似乎每个函数都应该返回自己的索引值,但实际上,每个函数都返回10。因为每个函数的作用域链中都保存着createFunctions函数的活动对象,所以他们引用的都是这个createFunctions函数的活动对象中的变量i,在createFunctions函数返回之后,变量i的值是10,此时每个函数都引用着保存变量i的同一个变量对象,所以每个函数内部i的值都是10。

我们以调用functions[3]()为例,图解一下:

Closure函数的Function对象的作用域链引用的createFunctions的活动对象中保留的变量i的值为10。所以不管是functions[3]()还是functions[5](),其运行时上下文的作用域链引用的createFunctions的活动对象都是同一个活动对象,该活动对象中保留的变量i的值是10。

如何避免这种局面?我们可以通过创建另一个匿名函数让闭包的行为符合预期。

function createFunctions(){
 var result = new Array();
 for (var i = 0; i < 10; i++){
 result[i] = function(num){
 return function(){
 return num;
 }
 }(i);
 }
 return result;
}
var functions = createFunctions();
for(var i = 0; i < functions.length; i++){
 console.log(functions[i]());
}

输出的结果是

0 1 2 3 4 5 6 7 8 9

这个代码片段与前面的代码的区别在于立即调用了一个匿名函数function(num),使得闭包function()引用的是function(num)的活动对象,访问的是该活动对象中的变量num而不是createFunctions活动对象中的变量i,而在立即调用function(num)的num是索引值0,1,2…9。

我们仍旧以调用functions[3]()为例,图解一下:

在执行createFunctions函数的时候,会依次调用function(0), function(1) … function(9), 生成function(0), function(1) … function(9)这10个function(num)的活动对象,而result[0], result[1] … result[9]这10个匿名函数对象的作用域链分别引用这10个function(num)的活动对象,而其中的变量num的值也对应的为0, 1 … 9。

所以不管是functions[3]()还是functions[5](),其运行时上下文的作用域链都会引用在执行createFunctions函数时候所执行的function(3)或者function(5)这些function(num)函数的活动对象,这些活动对象都是不同的活动对象,其中保留的num值分别为3, 5。

更多关于JavaScript相关内容感兴趣的读者可查看本站专题:《javascript面向对象入门教程》、《JavaScript错误与调试技巧总结》、《JavaScript数据结构与算法技巧总结》、《JavaScript遍历算法与技巧总结》及《JavaScript数学运算用法总结》

希望本文所述对大家JavaScript程序设计有所帮助。

显示全文