JavaScript 閉包 詳解
阿新 • • 發佈:2019-01-02
閉包 : 閉包就是一個函式引用另外一個函式的變數,因為變數被引用著所以不會被回收,因此可以用來封裝一個私有變數當內部函式在定義它的作用域的資料外部被引用時,就建立了該內部函式的閉包,如果內部函式引用了位於外部函式的變數,當外部函式呼叫完畢後,這些變數在記憶體不會被釋放,因為閉包需要它們變數的作用域 : 作用域就兩種,全域性作用域和區域性作用域var n=999;function f1(){ alert(n);}f1(); // 999function f2(){ var m=999;}alert(m); // errorfunction f3(){ i=999; // 函式內部宣告變數的時候,一定要使用 var 宣告變數,如果不用 var,此時改變數就變成全域性變數}f3();alert(i); // 999從外部讀取區域性變數 : 正常情況下是辦不到的,但可以在函式的內部再定義一個函式,這樣內部函式就可以訪問外部函式的變數。另外,外部函式無法訪問內部函式變數,這就是 JavaScript 語言特有的 "鏈式作用域" 結構function f1() { var n = 999; function f2() { alert(n); } return f2;}var result = f1();result(); // 999閉包可以用在許多地方。它的最大用處有兩個,一個是前面提到的可以讀取函式內部的變數,另一個就是讓這些變數的值始終保持在記憶體中function f1() { var n = 999; nAdd = function(){ // nAdd 是全域性變數 n += 1; } function f2() { alert(n); } return f2;}var result = f1();result(); // 999 nAdd();result(); // 10001> 由於閉包會使得函式中的變數都被儲存在記憶體中,記憶體消耗很大,所以不能濫用閉包,否則會造成網頁的效能問題,在IE中可能導致記憶體洩露。解決方法是,在退出函式之前,將不使用的區域性變數全部刪除2> 閉包會在父函式外部,改變父函式內部變數的值。所以,如果把父函式當作物件 (object) 使用,把閉包當作它的公用方法(Public Method),把內部變數當作它的私有屬性(private value),這時一定要小心,不要隨便改變父函式內部變數的值var name = "The Window";var object = { name : "My Object", getNameFunc : function() { return function() { return this.name; }; }, getNameFunc2 : function() { return () => this.name; }, getNameFunc3 : function() { this_ = this; return function() { return this_.name; }; }};alert(object.getNameFunc()()); // The Window,this 指向呼叫的物件,此處執行的時全域性 this alert(object.getNameFunc2()()); // My Object,使用箭頭函式相當於 getNameFunc3 的寫法alert(object.getNameFunc3()()); // My Objectfunction outerFun() { var a =0; alert(a); }var a = 4;outerFun(); // 0alert(a); // 4function outerFun() { a = 0; // 沒有 var,此時 a 是作用於全域性變數,將修改全域性變數的 a alert(a); }var a=4; // 全域性變數 aouterFun(); // 0alert(a); // 0function createFunctions() { var result = new Array(); for (var i=0; i < 10; i++) { result[i] = function() { return i; }; } return result;}var funcs = createFunctions();for (var i=0; i < funcs.length; i++) { // 打印出 10 個 10,在 js 中使用 () 才會執行函式 console.log(funcs[i]());}