JavaScript函数(三)——闭包及作用域
程序员文章站
2022-03-31 17:07:34
闭包 概念 只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁 例子 作用:比如在一个函数中嵌套一个函数,通过闭包可以让嵌套函数访问到包裹它的函数的局部变量。 封装 闭包陷阱 总结 优点:灵活方便,封装 缺点:空间 ......
闭包
概念
只有函数内部的子函数才能读取局部变量,所以闭包可以理解成“定义在一个函数内部的函数“。在本质上,闭包是将函数内部和函数外部连接起来的桥梁
例子
function outer(){ var localVal = 30; return localVal; } outer();//30 function outer(){ var localVal = 30; return function() { return localVal; } } var func = outer(); func();//30
作用:比如在一个函数中嵌套一个函数,通过闭包可以让嵌套函数访问到包裹它的函数的局部变量。
封装
(function(){ var _userId = 123; var _typeId = 'item'; var export = {}; function converter(userId){ return + userId; } export.getUserId = function(){ return converter(_userId); } export.getTypeId = function(){ return _typeId; } window.export = export; })(); export.getUserId();//123 export.getTypeId();//item export._uerId;//undefined export._typeId;//undefined export.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<tasks.length; j++) { tasks[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); }
总结
优点:灵活方便,封装
缺点:空间浪费,内存泄漏,性能消耗
上一篇: AngularJS路由变化 监听方法