对闭包的理解
从网上看了一些关于js闭包的文章,现在总算是明白之前遇到过的一系列问题,比如:
function a() { var nodes = [1,2,3,4,5]; var arr = []; for(var i=0; i<nodes.length; i++) { return function() { arr[i] = i; } } return arr; } var b = a(); alert(b);
比如这段看似没什么语法问题的代码,为啥返回结果会让人如此的蛋疼呢?我想如果不理解或不知道闭包的话,这个问题还真回答不了,其中闭包涉及到了关于执行环境、作用域链等js中比较难理解且又很重要的概念,关于这些概念,我相信baidu或google会有很多文章说明,我技术有限,基本上没能力解释清楚。在此只想show一下我在看这些文章时候对例子的一点想法,仅供参考^_^!
//理解闭包 function a() { var n = 2;//私有变量,只有作用域链包含变量n的函数(方法)有权访问n function b() { alert(n); } return b; //var b = function() {//功能同上 //alert(n); //}(); } var c = a();//c()是一个外部方法,如果没有闭包,它无法访问a()的私有变量 c();//此时c()函数“可以访问”(间接访问)a的私有变量, //在a()执行完后,其私有变量n(包括a和b对象)并没有被销毁(暂时保存在内存中), //因为c()的执行依赖b(),b()的执行依赖变量n,且b()有权访问变量n,这就形成了所谓的闭包 //闭包的特性 function print(str) { document.write(str + ' '); } var outer = []; function clouseTest() { for(var i=0; i<5; i++){ var obj ={}; obj.func = function() {//实际上,这个函数并未执行 print(i);//在这里,i可以是任何值或变量 print('任何值'); }; outer.push(obj); } }; clouseTest();//此时i的值是5 outer[0].func();//5,任何值 outer[1].func();//5,任何值 outer[2].func();//5,任何值 outer[3].func();//5,任何值 outer[4].func();//5,任何值 alert(toString(outer[0].func())); function clouseTest2() { for(var i=0; i<5; i++){ var obj ={}; obj.func = function(no) {//申明一个匿名函数并立即执行它 return function() { print(no);//可以访问i变量 } }(i);//闭包函数被执行并返回了值,这样,外部函数就可以间接访问函数内部的变量了 outer.push(obj); } //i的值是5 }; clouseTest2(); outer[0].func();//0 outer[1].func();//1 outer[2].func();//2 outer[3].func();//3 outer[4].func();//4 function clouseTest3() { for(var i=0; i<5; i++){ var obj ={}; obj.func = function() {//此时func变成了obj对象的一个属性而已 print(i); }(); outer.push(obj); } }; clouseTest3();//此时i的值是5 outer[0].func;//0,此时func变成了obj对象的一个属性而已 outer[1].func;//1 outer[2].func;//2 outer[3].func;//3 outer[4].func;//4 /* * 例子来自《JavaScript高级程序设计》(第2版) */ function createFunctions(){ var result = new Array(); for (var i = 0; i < 3; i++) { result[i] = function(){ return i; }; } return result; } var funcs = createFunctions();//因createFunctions()返回数组(result),funcs直接指向了result[i]() for (var i = 0; i < funcs.length; i++) { //document.write(funcs[i]()+''); alert(funcs[i]);//返回3个function(){return i;}函数本身,其中i的值是3 } //闭包应该注意的问题 * 1、由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成 * 网页的性能问题,在IE中可能导致内存泄露。解决方法是,在退出函数之前,将不使用的局部变量全部删除。 * 2、闭包会在外部函数改变内部函数的变量值。所以,如果你把外部函数当作对象(object)使用,把闭包 * 当作它的公用方法(Public Method),把内部变量当作它的私有属性(private value),这时一定要小心, * 不要随便改变外部函数内部变量的值。 //理解闭包了??? var name = 'window'; var test1 = { name : 'me', getName : function() { return function() { return this.name; } } }; alert(test1.getName()());//输出'window' var test2 = { name : 'me', getName : function() {//特权方法,参阅“javascript私有成员”一文 var that = this; return function() { return that.name; } } }; alert(test2.getName()());//输出'me'
还剩下一个问题就是闭包有什么用?这个我觉得还是自己去实践中摸索归纳比较好,这里推荐一篇觉得说的比较好的文章: