闭包
概念
只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁
例子
function outer(){ var localVal = 30; return localVal;}outer();//30function outer(){ var localVal = 30; return function() { return localVal; }}var func = outer();func();//30
作用:比如在一个函数中嵌套一个函数,通过闭包可以让嵌套函数访问到包裹它的函数的局部变量。
封装
(function(){ var _userId = 123; var _typeId = 'item'; var MyExport = {}; function converter(userId){ return + userId; } MyExport.getUserId = function(){ return converter(_userId); } MyExport.getTypeId = function(){ return _typeId; } window.MyExport = MyExport;})();MyExport.getUserId();//123MyExport.getTypeId();//itemMyExport._uerId;//undefinedMyExport._typeId;//undefinedMyExport.converter;//undefined
闭包陷阱
var tasks = [];for (var i=0; i<3; i++) { tasks.push(function() { console.log('>>> ' + i); });}console.log('end for.');for (var j=0; j
输出结果都为3。这个问题的原因在于,函数创建时并未执行,所以先打印end for.,然后才执行函数,由于函数引用了循环变量i,而i的作用域是整个函数,而不是循环,在函数执行时,i的值已经变成了3。
解决方法
再创建一个函数,将循环变量作为函数参数传入:var tasks = [];for (var i=0; i<3; i++) { var fn = function(n) { tasks.push(function() { console.log('>>> ' + n); }); }; fn(i);}//简化语法,直接用匿名函数的立即执行模式(function() { ... })()var tasks = [];for (var i=0; i<3; i++) { (function(n) { tasks.push(function() { console.log('>>> ' + n); }); })(i);}
总结
优点:灵活方便,封装
缺点:空间浪费,内存泄漏,性能消耗