红宝书上对于闭包的定义:闭包是指有权访问另外一个函数作用域中的变量的函数。
function f() {
var n = 10;
return function fn() {
n++;
console.log(n);
};
}
console.log(n); //undefined
var x = f(); //x 为返回fn
x(); //输出 11
其中 fn 就是一个闭包,在函数 f 外部无法访问内部变量 n,由于 fn 存在函数 f 内部的,可以访问外部变量 n(存在 fn 函数作用域链上),将 fn return
出来,可以从外部访问到 f 内部变量 n。即 fn 使得从最外面全局作用域访问到了函数 f 作用域上的变量 n,闭包
经典闭包案例
for (var i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
i
变量始终在一个作用域,所以循环结束只有i
增加到了 5
for (var i = 0; i < 5; i++) {
!(function (i) {
setTimeout(() => {
console.log(i);
}, 0);
})(i);
}
//上面方法和下面等价,立即执行函数的另一种写法
for (var i = 0; i < 5; i++) {
(function (i) {
setTimeout(() => {
console.log(i);
}, 0);
})(i);
}
变量i
作为立即执行函数参数传入,i 作为立即执行函数的形参是函数内的局部变量,存在独立作用域中,外部变量 i 的变化不影响内部变量变化。
同样使用 let,每一次循环开启新的块级作用域,不影响下一次循环
for (let i = 0; i < 5; i++) {
setTimeout(() => {
console.log(i);
}, 0);
}
总结:闭包是函数嵌套函数,使得函数内部作用域的变量可以被外部函数访问。
闭包的作用
- 实现封装,属性私有化
- 模块化开发,防止污染全局变量,保护函数内的变量安全(外部可以访问,但是不可以修改)
闭包的缺点
由于 内部函数被 return,局部作用域内的变量不能及时回收,所以滥用闭包会导致消耗内存,容易导致内存泄露,所以一定要及时手动回收。
网友评论