概述
在介绍闭包之前,我们先来了解一下JavaScript的垃圾回收机制。在javaScript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收,否则这个对象会一直保存在内存中。
比如在下面的例子中:
- 内部函数innerFoo()定义在外部函数foo()中,因此innerFoo()依赖于foo()
- 而全局变量fn又引用了innerFoo(),所以foo()间接被fn引用。因此foo()不会被垃圾回收,会一直保存在内存中。
闭包的原理
闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。
var a = 10;
function Add(){
a++;
console.log(a);
}
Add();
Add();
Add();
如果上述程序还有其他函数也会用到a变量,这个时候a的值很容易被修改,比较不安全,这就是全局变量容易污染的原因,所以我们必须解决变量污染的问题,那就是把变量封装到函数内,让它成为局部变量。现在我们需要一种既不污染全局变量,在外部也可以访问到某局部变量的方法,那么闭包就出现了。
var a = 10;
function Add3(){
var a = 10;
return function(){
a++;
return a;
};
};
var cc = Add3();
console.log(cc());
console.log(cc());
console.log(cc());
console.log(a);
应用
for (var i = 1;i <= 5;i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000)
}
//使用闭包
for (var i = 1;i <= 5;i++) {
(function (i) {
return setTimeout(function timer() {
console.log(i);
}, i * 1000);
})(i)
}
//let块状作用域
for (let i = 1;i <= 5;i++) {
setTimeout(function timer() {
console.log(i);
}, i * 1000);
}