閉包的定義:
閉包指有權存取另一個函數作用域中的變數的函數。
這裡採用另一個定義:
當函數可以記住並存取所在的詞法作用域時,就產生了閉包,即使函數在定義時的詞法作用域以外的地方被呼叫。
第一點:JavaScript是基於詞法作用域的,詞法作用域意味著作用域是由書寫程式碼時函數宣告的位置來決定的。
詞法作用域查找規則:作用域查找會在找到第一個符合的識別碼時停止。在多層的嵌套作用域中可以定義同名的標識符,這叫作「遮蔽效應」(內部的標識符「遮蔽」了外部的標識符)。拋開遮蔽效應,作用域查找總是從運行時所處的最內部作用域開始,逐級向外或者說向上進行,直到遇見第一個匹配的標識符為止。
無論函數在哪裡被調用,也無論它如何被調用,它的詞法作用域都只由函數被宣告時所處的位置決定。
第二點: JavaScript 具有基於函數的作用域,函數是 JavaScript 中最常見的作用域單元。 函數作用域的意義是指,屬於這個函數的全部變數都可以在整個函數的範圍內使用及復用(事實上在嵌套的作用域中也可以使用),外部作用域無法存取包裝函數內部的任何內容。
第三點:JavaScript中的function是first-class object
1)可被賦於變量,數組元素與其他物件的屬性(property)
2)可以作為參數傳遞給函數
3)可以作為函數的回傳值
第四點:閉包
function foo() { var a = 2; function bar() { console.log( a ); // 2。bar()对 a 的引用的方法是词法作用域的查找规则,而这些规则只是闭包的一部分 } bar(); } foo();
上面程式碼其實並沒有真正使用閉包,閉包的應用一般分兩種情況-函數作為回傳值,函數作為參數傳遞。
改寫上面的程式碼:
function foo() { var a = 2; function bar() { console.log( a ); } return bar;//函数作为返回值}var baz = foo(); baz(); // 2 —— 朋友,这就是闭包的效果。
這裡函數 bar() 的詞法作用域能夠存取 foo() 的內部作用域。然後我們將 bar() 函數本身當作一個值類型傳遞。在這個範例中,我們將 bar 所引用的函數物件本身當作傳回值。
在這個例子中,bar() 在自己定義的詞法作用域以外的地方執行。 foo()函數回傳後其內部作用域依然存在,bar() 依然持有對該作用域的引用,而這個引用就叫作閉包。
再寫一個函數作為參數傳遞的範例:
var max = 10, fn = function(x) { if (x > max) {//注意词法作用域规则,这里的max是10,而不是100. console.log(x); //15 } }; (function(f) { var max = 100; f(15); })(fn);
第五點:JavaScript的垃圾回收機制GC
在js中,如果一個物件不在被引用,那麼這個物件會被GC回收,否則這個物件會一直保存在記憶體中
第六點:執行環境、活動物件、作用域以及作用域鏈
#某個執行環境中的所有程式碼執行完畢後,該環境被銷毀,所有保存在其中的變數和函數也隨之被銷毀。
當某個函數被呼叫時,會建立一個執行環境及對應的作用域鏈,使用arguments和與其它命名參數的值來初始化活動物件。
但是有些情況下,函數呼叫完成之後,其執行環境的作用域鏈會被銷毀,但是它的活動物件仍然留著記憶體中。這就是需要理解閉包的核心內容。
以上是對js閉包的簡單理解的詳細內容。更多資訊請關注PHP中文網其他相關文章!