閉包的理解

2021-08-17 01:23:31 字數 2521 閱讀 4911

閉包:是指有權訪問另乙個函式作用域中的變數的函式。建立閉包的常見方式就是在乙個函式內部建立另乙個函式

在函式createcomparisonfunction()中返回了乙個匿名函式,建立了乙個閉包。

當匿名函式被返回時,其作用域鏈包含外部函式createcomparisonfunction的作用域鏈,這樣匿名函式就能訪問外部函式createcomparisonfunction定義的變數了。(因為作用域鏈的訪問機制)更重要的是外部函式執行完畢後,其作用域鏈銷毀,但其活動物件不會銷毀,因為在匿名函式的作用域鏈在引用它,直到匿名函式被銷毀才會銷毀。

作用域鏈的最前端是當前**的執行環境的變數物件(活動物件),下乙個變數物件是其的包含環境,再下乙個是下乙個的包含環境,這樣作用域鏈的末端就是全域性執行環境。內部環境在作用域鏈的最前端,外部環境在其後面。由於識別符號解析沿著作用域鏈一級一級的搜尋識別符號直到找到。因此內部環境可以通過作用域鏈訪問到所有外部環境,但是外部環境不能訪問內部環境的任何變數和函式。

對於外部函式createcomparisonfunction來說,它的作用域鏈最前端是自己的活動物件,裡面儲存著atguments和propertyname,接下來是它的包含環境即全域性變數物件;對於匿名函式,它的作用域鏈最前端就是閉包本身的活動物件,裡面儲存arguments和object1,object2.接下來是其包含環境createcomparisonfunction的活動物件,最後就是全域性活動物件。

閉包儲存的是整個變數的物件而不是變數的某個特殊值,因此閉包智慧型取得任何變數的最後乙個值。

function

createfunction

(); }

return result;

}

上面的函式結果輸出全是10,這是因為每次呼叫匿名函式時其作用域鏈儲存的都是createfunction()函式的活動物件,因此引用的都是同乙個變數i。當createfuction()返回後,變數i的值都是10,此時每個匿名函式都引用者儲存變數i 的同乙個變數,所以在每個函式內部i的值都是10那麼要如何讓閉包符合預期呢?

function

createfunction

(); }(i);

}return result;

}

這樣修改後能返回不同索引值是因為:沒有把某一時刻i的特殊主直接賦值給陣列,而是定義了乙個立即執行的匿名函式將其賦值給陣列。在這個匿名函式裡面,接受i的特殊值作為引數,由於立即執行,此時將i的特殊值按值傳遞給num,而在立即執行的匿名函式內部又建立了乙個訪問num 的閉包,這樣result陣列的每個函式都有自己的num副本(儲存i的特殊值),就讓閉包的結果符合預期。

匿名函式的執行環境有全域性性,其this物件通常指向window

var name='the  window';

var object=

}};alert(object.getnamefunc()()); //the window

上面呼叫object.getnamefunc(),返回的是the window而不是沒有my object

我們把最後的一句拆成兩個步驟執行:

var first = object.getnamefunc();

var second = first();

其中第一步,獲得的first為返回的匿名函式,此時的getnamefunc()作為object的方法呼叫,如果在getnamefunc()中使用this,此時的this指向的是object物件。

第二步,呼叫first函式,可以很清楚的發現,此時呼叫first函式,first函式沒有在物件中呼叫,因此是作為函式呼叫的,是在全域性作用域下,因此first函式中的this指向的是window。

由於每個函式在被呼叫時會自動取得this.arguments,函式搜尋時只會搜尋到其活動物件為止,因此永遠不可能直接訪問外部函式中的這兩個變數。

那麼,如何獲得外部作用域中的this呢?

可以把外部作用域中的this儲存在閉包可以訪問到的變數裡。如下:

var name = "the window";

var object = ;

}}alert(object.getnamefunc()()); // "my object"

複製**

其中,getnamefunc()執行時的活動物件有:that/age/匿名函式,在執行匿名函式時,同時引用了getnamefunc()中的活動物件,因此可以獲取that和age的值。但是由於是在全域性環境中呼叫的匿名函式,因此匿名函式內部的this還是指向window。

閉包的理解

function a return b b不能直接越過a在全域性作用 var c a c i 1var inner 定義 function outer outer 呼叫 inner 呼叫function outer x return inner var i outer 3 i 3 輸出6特點 1 函...

閉包的理解

function f1 alert a 報錯 a is not defined這裡的a是區域性變數,函式內部可以訪問外部變數,但是外部不可以訪問內部變數。因此會報錯 值得注意的是 函式內部宣告變數的時候,一定要使用var命令。如果不用的話,實際上是宣告了乙個全域性變數。function f1 ret...

閉包的理解

有的時候容將閉包和匿名函式混淆 什麼時候會有閉包的問題呢?只要在設計巢狀函式時才有閉包問題。關鍵之處在於它能不能訪問定義體之外定義的非全域性變數。閉包是一種函式,他會保留定義函式時存在的自由變數的繫結。自由變數 未在本地作用域中繫結的變數 注意下面的例子 這時候會報錯 count 是數字或者任意不可...