接著上一節講的話,應該輪到“執行上下文棧”了,但是這裡不得不插入一節,把this說一下。因為this很重要,js的面試題如果不出幾個與this有關的,那出題者都不合格。
其實,this的取值,分四種情況。我們來挨個看一下。
在此再強調一遍一個非常重要的知識點:在函式中this到底取何值,是在函式真正被呼叫執行的時候確定的,函式定義的時候確定不了。因為this的取值是執行上下文環境的一部分,每次呼叫函式,都會產生一個新的執行上下文環境。
情況1:建構函式
所謂建構函式就是用來new物件的函式。其實嚴格來說,所有的函式都可以new一個物件,但是有些函式的定義是為了new一個物件,而有些函式則不是。另外注意,建構函式的函式名第一個字母大寫(規則約定)。例如:Object、Array、Function等。
以上程式碼中,如果函式作為建構函式用,那麼其中的this就代表它即將new出來的物件。
注意,以上僅限new Foo()的情況,即Foo函式作為建構函式的情況。如果直接呼叫Foo函式,而不是new Foo(),情況就大不一樣了。
這種情況下this是window,我們後文中會說到。
情況2:函式作為物件的一個屬性
如果函式作為物件的一個屬性時,並且作為物件的一個屬性被呼叫時,函式中的this指向該物件。
以上程式碼中,fn不僅作為一個物件的一個屬性,而且的確是作為物件的一個屬性被呼叫。結果this就是obj物件。
注意,如果fn函式不作為obj的一個屬性被呼叫,會是什麼結果呢?
如上程式碼,如果fn函式被賦值到了另一個變數中,並沒有作為obj的一個屬性被呼叫,那麼this的值就是window,this.x為undefined。
情況3:函式用call或者apply呼叫
當一個函式被call和apply呼叫時,this的值就取傳入的物件的值。至於call和apply如何使用,不會的朋友可以去查查其他資料,本系列教程不做講解。
情況4:全域性 & 呼叫普通函式
在全域性環境下,this永遠是window,這個應該沒有非議。
普通函式在呼叫時,其中的this也都是window。
以上程式碼很好理解。
不過下面的情況你需要注意一下:
函式f雖然是在obj.fn內部定義的,但是它仍然是一個普通的函式,this仍然指向window。
完了。
看到了吧,this有關的知識點還是挺多的,不僅多而且非常重要。
最後,既然提到了this,有必要把一個非常經典的案例介紹給大家,又是jQuery原始碼的。
以上程式碼是從jQuery中摘除來的部分程式碼。jQuery.extend和jQuery.fn.extend都指向了同一個函式,但是當執行時,函式中的this是不一樣的。
執行jQuery.extend(…)時,this指向jQuery;執行jQuery.fn.extend(…)時,this指向jQuery.fn。
這樣就巧妙的將一段程式碼同時共享給兩個功能使用,更加符合設計原則。
好了,聊完了this。接著上一節繼續說“執行上下文棧”。
注意:還有一部分this的內容本文中沒有講到,已經補充到這裡:http://www.cnblogs.com/wangfupeng1988/p/3996037.html
---------------------------------------------------------------------------
本文已更新到《深入理解javascript原型和閉包系列》的目錄,更多內容可參見《深入理解javascript原型和閉包系列》。
另外,歡迎關注我的微博。
學習作者教程:《前端JS高階面試》《前端JS基礎面試題》《React.js模擬大眾點評webapp》《zepto設計與原始碼分析》《json2.js原始碼解讀》