首页 > 代码库 > JavaScript 小记 之 闭包(Closures)

JavaScript 小记 之 闭包(Closures)

Closures are functions that refer to independent (free) variables.

闭包是以静态方式/词法方式进行存储所有父作用域的一个函数

在JavaScript高级程序设计里面通过一个 createComparisonFunction() 函数和这个函数的作用域链之间的关系图说得很明白为什么闭包可以访问外部函数的变量, 是因为闭包的作用域链不仅包括自己本地的活动对象, 还包括外部函数作用域链所指向的活动对象.

在JavaScript高级程序设计, JavaScript精粹 都有一个类似的例子 在循环里创建闭包.

(为了测试, 做了一点点修改)

 1 var fn = function() { 2     var result = []; 3     for(var i = 0; i < 3; i++) { 4         result[i] = function() { 5             console.log(i);     6         }; 7     } 8     return result;  9 };  10 11 var list = fn();12 list[0]();   //313 list[1]();   //3
14 list[2]();   //3
 1 var fn = function() { 2     var result = []; 3     for(var i = 0; i < 3; i++) { 4         result[i] = (function(num) { 5             return function() { 6                 console.log(num); 7             }; 8         })(i); 9     }10     return result; 11 };  12  13 var list = fn();14 list[0]();   //015 list[1]();   //116 list[2]();   //2

当时为了让自己可以了解得更彻底 自己也把作用域链画了出来 希望对部分同学有用

第一个函数作用域关系图:

技术分享

从第一个函数的作用域关系图可以看出 之所以数组里的每个函数都打印3是因为每个函数在各自本地的活动对象里都找不到 i 所以继续往上找 在外部函数的活动对象里找到了i 但是此时的i 在循环结束后值为3 所以每个函数打印均为3

第二个函数作用域关系图:

技术分享

第二个函数把一个立即执行的函数赋给了result数组, 并传入了i 所以此时result[x]的活动对象里就多一个变量num 值为 i (函数参数按值传递) 所以返回的函数打印num时 根据作用域链找到了result[x] 活动对象里的num 并打印出 num的值

 

通过画这两个函数的作用域链关系图, 就可以清楚地弄懂闭包的工作原理, 也就不会对闭包那么害怕啦! 

PS. 上面两个例子在JSLint 里都是会报错的: Don’t make functions within a loop

所以大家在实际的程序当中就不要这样使用 可以在循环外变量定义函数后再在循环里使用

最后附上 sublime-text 3 怎么安装SublimeLinter 的教程 http://www.sublimelinter.com/en/latest/installation.html

 

如有错误 欢迎指正 : ) 

 

JavaScript 小记 之 闭包(Closures)