前言:高程這本書真是神奇,每複習一遍,都會有新的收穫。話說我看書有個習慣,要是看得似懂非懂的地方就喜歡打個“?”。這次看到高程第七章“函數表達式”關於閉包與this對象的部分,發現已經積攢了2個問號了。之前過了兩遍都沒有完全弄明白! 好在如今對this的指向、函數的理解已經今非昔比,這一次終於讓我....
前言:高程這本書真是神奇,每複習一遍,都會有新的收穫。話說我看書有個習慣,要是看得似懂非懂的地方就喜歡打個“?”。這次看到高程第七章“函數表達式”關於閉包與this對象的部分,發現已經積攢了2個問號了。之前過了兩遍都沒有完全弄明白!
好在如今對this的指向、函數的理解已經今非昔比,這一次終於讓我打通這條堵塞的經脈,讓他融入我的知識體系了!!想想真是有些小激動呢~~
目的:一句話,本文就是解釋為什麼如下兩篇代碼中this.name的指向不同。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //The Window
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //My Object
正文:首先,我們得知道當函數調用過程中發生了什麼。
當函數被調用時,會自動創建兩個變數:this和arguments。這兩個變數有個特點,他們的搜索範圍僅限被調用函數的活動對象。什麼意思呢?arguments對象大家一定很清楚,保存函數的傳參的副本。看如下代碼:
function father (a) { var result=a; var result2=null; function son (a) { result2=a; } return result+" and "+result2; } father(123); //"123 and null"
這裡創建了兩個函數,father和son,其中son作為father函數內部的函數。 他們都接受傳參a。在這裡我們傳入傳參123,返回father與son獲得的傳參結果。
結果顯示father的傳參為123,而son的傳參為null,這個結果是顯而易見的。在這裡貼這麼弱智的代碼的用意是想說明son在搜索a這個變數時只搜索自己的活動變數而不會通過作用域鏈向上到father中去搜索。同樣的道理使用於this。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ return function(){ return this.name; }; } }; alert(object.getNameFunc()()); //The Window
這裡最內層匿名函數this為什麼指向的是window而不是他的上層函數getNameFunc。之前已經說明瞭this作為特殊的變數他的搜索範圍同arguments一樣僅限於自身的活動對象。也就是說內層匿名函數的this就算在自己這兒搜不到結果也不會再去他的上層函數getNameFunc中搜索。這個問題可以等同於——最內層匿名函數的this為什麼指向的是window?
如果我們將最後的結果賦給一個變數來說明會簡單汗多。
var result=object.getNameFunc()();
result變數是一個全局變數,他保存的指針指向getNameFunc最內層匿名函數的結果。訪問這個變數其實調用的不是getNameFunc函數,而是getNameFunc內部的匿名函數。也就是說這個匿名函數是在全局作用域中調用的,那麼匿名函數的this理所當然的指向window。
有了前面的解釋,第二段代碼就很好解釋了。
var name = "The Window"; var object = { name : "My Object", getNameFunc : function(){ var that = this; return function(){ return that.name; }; } }; alert(object.getNameFunc()()); //My Object
getNameFunc函數用that變數保存了他的this的指向,併在匿名函數中調用that變數。匿名函數在自己的活動對象中搜索到了that,並向上通過作用域鏈找到了that的出處。結果就顯而易見了。