函數內部又定義了一個函數,這個子函數就可以稱為閉包。
閉包的一個特點就是閉包內部可以引用外部函數的變量。
要理解閉包的原理,最重要的是要理解JavaScript的作用域鏈機制。
作用域
js中作用域分為兩種,全局作用域和函數作用域(局部作用域),此外js遵循的是靜態作用域規則。
作用域鏈
由作用域形成的鏈條就稱為作用域鏈,但這個作用域鏈存儲的是指向各個活動對象的指針。下面我們看下作用域鏈的具體形成過程:全局作用域是一直存在的,函數作用域只有在執行到它的時候才會生成,當函數被定義時,函數的`scope`屬性會存儲該函數外部的作用域下的活動對象(指針),包括全局變量對象,所以可能是個指針列表。然后我們在調用函數時,首先會為它創建一個執行環境,然后創建作用域鏈,這個作用域鏈先是復制`scope`屬性的值,新航道雅思培訓然后把自己的活動對象推入作用域鏈的前端,這個活動對象由該函數作用域下的變量構成,這樣函數的作用域鏈就形成了。
舉個栗子:
var g = 1;function out(){var out = "out";return function(){ var inner = "inner"; return out;
}
}示例圖
當函數執行完畢,作用域鏈就會被銷毀,之前占用的內存也會被釋放,但如果函數內部定義了一個子函數,這個時候子函數的`scope`屬性就會存儲著指向父函數活動對象的指針,活動對象由于仍被子函數引用,所以不會被銷毀,父函數的變量仍舊沒有被消除。變量out的值仍舊是“out”。
// 可通過如下代碼驗證var abc = out(); alert(abc());
結果:
閉包最常用的一個地方就是保留父函數的變量,這個在上面的例子中已經說明
閉包的另一個應用是模擬塊級作用域和私有變量,這是應用函數擁有自己的作用域的特點,在不想成為公有變量的變量外報上一層匿名函數并且立即執行
(function(){
// 這里是塊級作用域
})();閉包雖然看似簡單,但它揭示了js作用域鏈的機制,而且閉包有很多應用場景,如果不看懂它只會越來越懵逼。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。