闭包

111 阅读1分钟

MDN对闭包的定义为:

一个函数和对其周围状态(lexical environment,词法环境)的引用捆绑在一起(或者说函数被引用包围),这样的组合就是闭包(closure)。也就是说, 闭包让你可以在一个内层函数中访问到其外层函数的作用域。在 JavaScript 中,每当创建一个函数,闭包就会在函数创建的同时被创建出来。

也就是说,当外层函数的上下文已经被销毁了,我们依然可以访问到外层函数作用域下的值。

作用

闭包可以延展局部变量的生命周期。

缺点

函数内部的局部变量没有被释放,使得占用内存时间变长,容易造成内存泄漏。

题目

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = function () {
    console.log(i);
  };
}

data[0]();
data[1]();
data[2]();

答案都是3。原因是:

当执行到data[0]函数前,此时全局上下文的VO为:

globalContext = {
    VO: {
        data: [...],
        i: 3
    }
}

执行到data[0]函数时,data[0]上下文中没有i值,所以会从globalContext.VO中查找,i为3,所以打印的结果是3。

data[1]、data[2]同理。

如果用闭包:

var data = [];

for (var i = 0; i < 3; i++) {
  data[i] = (function (i) {
        return function(){
            console.log(i);
        }
  })(i);
}

data[0]();
data[1]();
data[2]();

当执行data[0]时,data[0]的匿名函数执行上下文中存有i:0,所以在data[0]执行时,能够在作用域链中找到i为0。结果打印就是0。