關於 JavaScript 閉包的簡單例子

於控制檯中運行以下例子:閉包

例 ①:無閉包

var x = [];
for (var i = 0; i < 9; i++) {
    setTimeout(function () {
        x[i] = i
    }, 1000)
}
console.log(i);
console.log(x);    // ▶(10) [empty × 9, 9]

例 ②:閉包

var y = [];
function doSetTimeout(i) {
    setTimeout(function () {
        y[i] = i;
    }, 1000);
}
for (var i = 0; i < 9; i++) {
    doSetTimeout(i);
}
console.log(i);
console.log(y);    // ▶(9) [0, 1, 2, 3, 4, 5, 6, 7, 8]

注意上述兩個例子中,函數

  • 例 ① 中,x = [empty × 9, 9]length10
  • 例 ② 中,y = [0, 1, 2, 3, 4, 5, 6, 7, 8]length9

由於循環體是 i++,循環結束 i = 9
咱們把 setTimeout等待時間改成0,再看結果:code

var y = [];
function doSetTimeout(i) {
    setTimeout(function () {
        y[i] = i;
    }, 0);
}
for (var i = 0; i < 9; i++) {
    doSetTimeout(i);
}
console.log(y);    // ▶(9) [0, 1, 2, 3, 4, 5, 6, 7, 8]

簡寫

var z = [];
for (var i = 0; i < 9; i++) {
    (function (i) {
        setTimeout(function () {
            z[i] = i;
        }, 1000)
    })(i);
}
console.log(z);

引伸

注意,若是咱們將上面的例子改成:io

var z = [];
for (var i = 0; i < 9; i++) {
    (function () {
        setTimeout(function () {
            z[i] = i;
        }, 1000)
    })();
}
console.log(z);    // ▶(10) [empty × 9, 9]

咱們看輸出結果是什麼,注意函數體中的 i 是函數體內部專有的仍是引用的全局變量?
而後,咱們進一步修改上述代碼,看看結果又會是否達到預期:console

var z = [];
for (var i = 0; i < 9; i++) {
    (function () {
        var j = i
        setTimeout(function () {
            z[j] = j;
        }, 1000)
    })();
}
console.log(z);
相關文章
相關標籤/搜索