一,闭包用途:
1,因为JS的变量具有不同的作用域,当外部想访问函数内部的局部变量时,需要通过闭包来实现;
2,闭包的另外一个好处是,让函数内部的变量保持在内存中,便于下次访问;
二,测试闭包
1,简单闭包使用
var addNum; function foo(){ // 函数局部变量 var num= 1; // 全局方法 addNum = function(){ num = num+1; console.log('addNum:'+num); } // 闭包函数 var getNum = function(){ console.log('getNum:'+num); return num; }; // 返回闭包 return getNum; }; // 获取闭包 var test = foo(); // 调用闭包,从而获得函数内部局部变量num的值 console.log(test()); // 调用全局方法,使函数内部局部变量num自加1,证明num=1是否仍在内存 addNum(); // 调用闭包,从而获得函数内部局部变量num的值 console.log(test());
测试结果:
getNum:1 1 addNum:1 getNum:2 2
2,循环调用闭包
function foo(){ var getNum=[]; for(i=0;i<3;i++){ // 闭包函数数组 getNum[i]=function(){ console.log('getNum:'+i); return i; } } // 返回闭包函数数组 return getNum; }; // 获取闭包函数数组 var test = foo(); // 调用闭包函数 console.log(test[0]()); console.log(test[1]()); console.log(test[2]());
预测会显示:0,1,2
结果被打脸了,显示全部为3
getNum:3 3 getNum:3 3 getNum:3 3
为啥会这样了,这是因为调用闭包函数去获取函数局部变量num时,只是获得num的变量引用,而这个引用最后指向了3;
解决方法:使用立即调用函数,在赋值闭包函数给getNumb时就立即调用,获得当前引用值,同时在本地保存这些引用值,再传递给闭包函数
修改后的代码
function foo(){ var getNum=[]; for(i=0;i<3;i++){ // 闭包函数数组,利用立即调用函数 getNum[i]=(function(i){ console.log('getLocalNum:'+i); var getLocalNum = function(){ return i; } return getLocalNum; })(i) } // 返回闭包函数数组 return getNum; }; // 获取闭包函数数组 var test = foo(); // 调用闭包函数 console.log('getNum'); console.log(test[0]()); console.log(test[1]()); console.log(test[2]());
显示的结果也说明了,立即调用函数在闭包赋值的时候就执行了
getLocalNum:0 getLocalNum:1 getLocalNum:2 getNum 0 1 2
三,注意事项:
1,正因为闭包把函数局部变量保留在内存,要注意内存泄露,或者爆满,不使用的变量记得注销掉;
2,闭包不仅可以访问函数局部变量,还能修改变量值,如果你不想在外部修改函数内部的变量,就得注意了;
Leave a Reply