# 闭包
闭包是指有权访问另一个函数作用域中的变量的函数。闭包是就是函数中的函数,里面的函数可以访问外面函数的变量,外面的变量的是这个内部函数的一部分。
闭包的作用:
- 使用闭包可以访问函数中的变量。
- 可以使变量长期保存在内存中,生命周期比较长。
闭包不能滥用,否则会导致内存泄露,影响网页的性能。闭包使用完了后,要立即释放资源,将引用变量指向 null。
使用闭包主要是为了设计私有的方法和变量。闭包的优点是可以避免全局变量的污染,缺点是闭包会常驻内存,会增大内存使用量,使用不当很容易造成内存泄露。
闭包有三个特性:
- 函数嵌套函数
- 函数内部可以引用外部的参数和变量
- 参数和变量不会被垃圾回收机制回收
# 闭包的使用场景
- 创建特权方法用于访问控制
- 事件处理程序及回调
- 利用闭包实现数据私有化或模拟私有方法。这个方式也称为模块模式(module pattern)
- 部分参数函数(partial applications)柯里化(currying)
- 封装变量,收敛权限。在函数外面根本没有接口修改私有变量和函数,保证了数据的安全。
- cached 对象储存。
- 封装私有变量
# 循环中使用闭包解决 var
定义函数的问题
for (var i = 1; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
解决方法有 3 种
第一种,使用立即执行函数
方式
for (var i = 1; i < 5; i++) {
(function(j) {
setTimeout(function timer() {
console.log(j);
}, j * 1000);
})(i);
}
第二种,使用 ES6 的let
, 因为对于 let
来说,他会创建一个块级作用域
for (let i = 1; i < 5; i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}
相当于
{ // 形成块级作用域
let i = 0
{
let ii = i
setTimeout( function timer() {
console.log( ii );
}, i*1000 );
}
i++
{
let ii = i
}
i++
{
let ii = i
}
...
}
第三种,使用 setTimeout
的第三个参数
for (var i = 1; i < 5; i++) {
setTimeout(
function timer(j) {
console.log(j);
},
i * 1000,
i,
);
}