摘要:首先來講講阮一峰的文章中的兩道思考題。環境記錄包含包含了函數內部聲明的局部變量和參數變量,外部引用指向了外部函數對象的上下文執行場景。
本文最主要講講JavaScript閉包和this綁定相關的我的小發現,鑒于這方面的基礎知識已經有很多很好的文章講過了,所以基本的就不講了,推薦看看酷殼上的理解Javascript的閉包和阮一峰的學習Javascript閉包(Closure),寫的都非常好。
首先來講講阮一峰的文章中的兩道思考題。
代碼片段一
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()());
這段代碼最后輸出的是
The Window
原因在同一片文章的評論中已經有人指出了
George Wing 說:
上面本人說得不太正確。
this的指向是由它所在函數調用的上下文決定的,而不是由它所在函數定義的上下文決定的。
對于最后返回的這個匿名函數
function(){ return this.name; };
它是作為一個獨立的函數返回的,它的調用域是在全局上,所以會輸出全局變量name。
代碼片段二
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()());
代碼片段二最后輸出的是
My Object
這里就要考慮var that = this;這句的作用了,由于getNameFunc是object內部的函數,所以它調用的上下文this保存的是object的信息,將其保存到that變量,這樣作為內部函數的匿名函數就可以直接訪問了。
可以注意到的是,阮一峰文章中的代碼,都是將通過一個JSON對象來訪問內部的函數,這樣其實有些地方還不夠清晰,畢竟不怎么嚴格地說,閉包就是函數內部的函數,所以我借用CoolShell上的文章中的例子來進一步說明。
代碼片段三
function greeting(name) { var text = "Hello " + name; // local variable // 每次調用時,產生閉包,并返回內部函數對象給調用者 return function() { alert(text); } } var sayHello=greeting("Closure"); sayHello() // 通過閉包訪問到了局部變量text
這段代碼輸出
Hello Closure
看上去好像很好理解,接下來看代碼片段四:
代碼片段四
var text = "findingsea"; function greeting(name) { var text = "Hello " + name; // local variable // 每次調用時,產生閉包,并返回內部函數對象給調用者 return function() { alert(this.text); } } var sayHello=greeting("Closure"); sayHello() // 通過閉包訪問到了局部變量text
這段代碼輸出
findingsea
這是為什么呢?
針對代碼片段三,CoolShell上的原文有解釋:
文法環境中用于解析函數執行過程使用到的變量標識符。我們可以將文法環境想象成一個對象,該對象包含了兩個重要組件,環境記錄(Enviroment Recode),和外部引用(指針)。環境記錄包含包含了函數內部聲明的局部變量和參數變量,外部引用指向了外部函數對象的上下文執行場景。全局的上下文場景中此引用值為NULL。這樣的數據結構就構成了一個單向的鏈表,每個引用都指向外層的上下文場景。
針對代碼片段四,就是我們之前講過的,this保存是調用環境下的上下文內容,所以會輸出全局的text。
總結本文想說明的是以下兩點:
在函數閉包中,不使用this對變量進行訪問時,函數會通過文法環境中的外部引用(指針),一級級地往上找(單向鏈表),直到找到(或者最終找不到)對應的變量。這個結構是在函數定義的時候就決定了的。
在函數閉包中,使用this對變量進行訪問時,和絕大多數語言不同,JavaScript的this保存的是調用環境的上下文,也就是說this中的內容是在調用的時候決定的,所以訪問到的是當前環境下的對應變量,并不會像前一種情況一樣進行逐級查找。
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/87555.html
摘要:最近剛剛看完了你不知道的上卷,對有了更進一步的了解。你不知道的上卷由兩部分組成,第一部分是作用域和閉包,第二部分是和對象原型。附錄詞法這一章并沒有說明機制,只是介紹了中的箭頭函數引入的行為詞法。第章混合對象類類理論類的機制類的繼承混入。 最近剛剛看完了《你不知道的 JavaScript》上卷,對 JavaScript 有了更進一步的了解。 《你不知道的 JavaScript》上卷由兩部...
摘要:全局的函數第個對象第個對象作為構造器進行調用也就是利用運算符進行調用。與操作的共同使用只有通過操作產生的對象,可以使用構造器函數原型鏈上的內容,否則對象只能使用自己原型鏈上的內容。 今天這個話題是因為這幾天看了《JavaScript忍者秘籍》,感覺這本書把這幾個內容講的蠻透徹了,特撰本文,以便日后翻閱。(應該都會以知識點的形式給出吧。) 函數 1.【基本類型】 JavaScript中函...
摘要:被調用的函數一定是在當前函數體內被調用的。所以,當前函數并沒有暫停,只是交出了控制權而已。它代表函數運行時,自動生成的一個內部對象,只能在函數內部使用。 函數 調用一個函數會暫停當前函數的執行,傳遞控制權和參數給新調用的函數,除了聲明時傳遞的形式參數外,每個函數還會接受兩個附加的參數: this和arguement. 其實在讀到這句話的的時候,我產生了兩個莫名其妙的疑問1.調用一個函數...
摘要:在代碼執行時,對應的作用域鏈常常是保持靜態的。當語句執行完畢后,會把作用域鏈恢復到原始狀態。在全局作用域中創建的函數,其作用域鏈會自動成為全局作用域中的一員。 列表項目 前言 學習了javascript已經很久了,關于這個語言中的這兩個特性也是早已耳熟能詳,但是在實際的使用的過程中或者是遇到相關的問題的時候,還是不能很好的解決。因此我覺得很有必要深入的學習并且記錄這個問題,以便在今后的...
摘要:閉包的學術定義先來參考下各大權威對閉包的學術定義百科閉包,又稱詞法閉包或函數閉包,是引用了自由變量的函數。所以,有另一種說法認為閉包是由函數和與其相關的引用環境組合而成的實體。 前言 上一章講解了閉包的底層實現細節,我想大家對閉包的概念應該也有了個大概印象,但是真要用簡短的幾句話來說清楚,這還真不是件容易的事。這里我們就來總結提煉下閉包的概念,以應付那些非專人士的心血來潮。 閉包的學術...
閱讀 3658·2021-11-15 11:37
閱讀 2317·2021-09-24 10:39
閱讀 2442·2021-07-25 21:37
閱讀 1428·2019-08-30 15:56
閱讀 2580·2019-08-30 15:55
閱讀 948·2019-08-30 15:54
閱讀 2120·2019-08-30 14:21
閱讀 851·2019-08-30 11:24