閉包 : 函數可以訪問它被創建時所處的上下文環境。---《JavaScript語言精粹》
產生原理: JavaScript中沒有塊級作用域,只有函數作用域,函數中任何位置定義的參數和變量在函數內的任何地方都是可見的,在函數外不可見。
使用方法: 可以通過在函數內部創建局部變量,實現變量的私有化。(外部不可見)
注意事項: 內部函數訪問外部函數的變量時訪問的是實際變量(值為外部函數返回時變量的值)。
知識點 : ①只要內部函數需要,外部函數中的變量不會在外部函數返回后銷毀。(多了浪費內存)
②通過定義內部函數實現對內部變量信息的查詢和修改,實現接口的暴露。
舉個例子:
var myObject = (function(){ var value=0; return { getValue: function(){ return value; }, setValue: function(v){ if (typeof v === 'number'){ value = v; } } }; }());
這段代碼得到一個myObject對象,包含兩個方法,只有這兩個方法可以獲取或者修改value變量,沒有其他辦法可以訪問到value變量。
這個value變量我們叫私有變量,這兩個可以訪問私有變量的共有方法就叫做特權方法。
再舉個例子:
//構造一個函數,本義是通過內部函數返回一個函數數組,數組中每一項都是一個函數
//數組項函數會返回當前的數組索引 //但是最后每一項的函數都會得到返回10 var eg2 = function(){ var i, result = new Array(); for(i=0; i<10; i += 1){ result[i] = function(){ return i; } } return result; };
為什么最后數組中每一項的函數都會返回10呢?因為內部的匿名函數訪問的是變量i而不是函數創建時i的值,在for循環執行完后變量i中保存的值為10,最后外部函數返回的result數組中的每一項的函數中返回的變量i的值也就為10。
可以修改成這樣解決:
//在for循環之外創建一個輔助函數,返回一個會返回傳入的值的函數 var eg2 = function(){ var result = new Array(); var helper = function(e){ return function(){ return e; } }; var i; for(i=0; i<10; i += 1){ result[i] = helper(i); } return result; };
在for循環中每次調用helper()函數時,傳入變量i,由於函數參數是按值傳遞的,helper()就會將當前的變量i的值復制給局部變量e,然后返回一個會返回變量e的函數。
這里的變量e是每個數組項函數的局部變量,各自保存着各自不同的值。