首頁 > web前端 > js教程 > JavaScript進階系列—閉包與引用

JavaScript進階系列—閉包與引用

黄舟
發布: 2017-02-08 09:46:08
原創
1078 人瀏覽過
  • 模擬私有變數

  • 為什麼不可以在外部存取私有變數

  • 循環中的閉包

  • 避免引用錯誤著當前作用域總是能夠存取外部作用域中的變數。 因為 函數 是 JavaScript 中唯一擁有自身作用域的結構,因此閉包的建立依賴函數。

  • 模擬私有變數
function Counter(start) {
    var count = start;
    return {
        increment: function() {
            count++;
        },

        get: function() {
            return count;
        }
    }
}

var foo = Counter(4);
foo.increment();
foo.get(); // 5
登入後複製

這裡,Counter 函數傳回兩個閉包,函數 increment 和函數 get。 這兩個函數都維持著 對外部作用域 Counter 的引用,因此總是可以存取此作用域內定義的變數 count。

為什麼不可以在外部存取私有變數

因為 JavaScript 中不可以對作用域進行引用或賦值,因此沒有辦法在外部存取count 變數。 唯一的途徑就是經過那兩個閉包。

var foo = new Counter(4);
foo.hack = function() {
    count = 1337;
};
登入後複製

上面的程式碼不會改變定義在 Counter 作用域中的 count 變數的值,因為foo.hack 沒有 定義在那個作用域內。它將會建立或覆蓋全域變數 count。

循環中的閉包

一個常見的錯誤出現在循環中使用閉包,假設我們需要在每次循環中調用循環序號

for(var i = 0; i < 10; i++) {
    setTimeout(function() {
        console.log(i);  
    }, 1000);
}
登入後複製

上面的程式碼不會輸出數字0 到9,而是會輸出數字10 十次。

當 console.log 被呼叫的時候,匿名函數保持對外部變數 i 的引用,此時for迴圈已經結束, i 的值被修改成了 10。

為了得到想要的結果,需要在每次循環中建立變數 i 的拷貝。

避免引用錯誤


為了正確的獲得循環序號,最好使用 匿名包裝器(譯者註:其實就是我們通常說的自執行匿名函數)。

for(var i = 0; i < 10; i++) {
    (function(e) {
        setTimeout(function() {
            console.log(e);  
        }, 1000);
    })(i);
}
登入後複製

外部的匿名函數會立即執行,並且把 i 作為它的參數,此時函數內 e 變數就擁有了 i 的一個拷貝。

當傳遞給 setTimeout 的匿名函數執行時,它就擁有了對 e 的引用,而這個值是不會被循環改變的。

有另一個方法完成同樣的工作,那就是從匿名包裝器中傳回一個函數。這和上面的程式碼效果一樣。

for(var i = 0; i < 10; i++) {
    setTimeout((function(e) {
        return function() {
            console.log(e);
        }
    })(i), 1000)
}
登入後複製

以上就是JavaScript進階系列—閉包與引用的內容,更多相關內容請關注PHP中文網(m.sbmmt.com)!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板