闭包原理

66 阅读2分钟

概述

在介绍闭包之前,我们先来了解一下JavaScript的垃圾回收机制。在javaScript中,如果一个对象不再被引用,那么这个对象就会被垃圾回收,否则这个对象会一直保存在内存中。

比如在下面的例子中:

  • 内部函数innerFoo()定义在外部函数foo()中,因此innerFoo()依赖于foo()
  • 而全局变量fn又引用了innerFoo(),所以foo()间接被fn引用。因此foo()不会被垃圾回收,会一直保存在内存中。

image.png

闭包的原理

闭包的实现原理,其实是利用了作用域链的特性,我们都知道作用域链就是在当前执行环境下访问某个变量时,如果不存在就一直向外层寻找,最终寻找到最外层也就是全局作用域,这样就形成了一个链条。

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);
}