JavaScript中的闭包

推荐参考MDN相应解析:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Closures

首先要知道什么是闭包?

答:总体印象就是函数中嵌套一个函数,且外部函数将嵌套的函数对象作为返回值。

其次值得注意的是:循环中创建闭包容易发生错误。

比如说:

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push(function () {
            return i * i;
        });
    }
    return arr;
}

var results = count();
var f1 = results[0];//16
var f2 = results[1];//16
var f3 = results[2];//16

按照上面的代码,本来以为会输出的分别是1,4,9,但结果确是16。

错误原因:赋值给 arr 的是闭包。这些闭包是由他们的函数定义和在 count 作用域中捕获的环境所组成的。这三个闭包在循环中被创建,但他们共享了同一个词法作用域。由于循环在事件触发之前早已执行完毕,变量对象i(被三个闭包所共享)已经指向了arr的最后一项。

解决方法:

方法一:使用匿名闭包。

function count() {
    var arr = [];
    for (var i=1; i<=3; i++) {
        arr.push((function (n) {
            return function () {
                return n * n;
            }
        })(i));
    }
    return arr;
}

var results = count();
var f1 = results[0];
var f2 = results[1];
var f3 = results[2];

f1(); // 1
f2(); // 4
f3(); // 9

方法二:将for循环中的var改为let,每个闭包绑定块作用域的变量。