JavaScript 核心觀念(40)-函式以及 This 的運作-最常見的 this:物件的方法調用
前言
接下來就會開始講一推讓許多 JavaScript 開發者煩惱的東西,也就是 this
。
最常見的 this:物件的方法調用
首先 this
基本上在 JavaScript 非常的常見,而且是不需要使用這設置就會存在的東西,這是什麼意思呢?
這邊先打開瀏覽器的控制台,並按下 source 中的暫停按鈕,接下來輸入以下程式碼
1 | function fn () { |
就會看到以下畫面
然後按下 「Step info next function call」就會進入該函式的執行堆疊,這時候就會看到 Scope 裡面會有一個 this
因此 this
只要在執行環境成立時,就會自動生成,因此並不需要我們特別去設定,除此之外在此我們也可以看到目前 this
是指向到 window
,因此若此時我們有一個 Global 變數,那麼我們就可以直接使用 this
取得
1 | var myName = 'Ray'; |
這邊再強調一次 this
並不需要我們特別去設定或是宣告,它本身在存活在每一個執行環境下,其中包含函式的執行環境以及全域執行環境,因此基本上 this
也有一些基本觀念要注意
第一個是我們剛剛一直在強調的,每一個執行環境都有屬於自己的關鍵字 this
,第二個觀念若能熟悉的話,基本上大多 this
的指向都可以了解,最後一個則是嚴格模式。
而這邊課程也有列出常見的 this
調用方式
那麼這邊回歸 this
有什麼用呢?
基本上 this
它的指向與我們怎麼定義它並沒有太大的什麼關係,因此它是可以略過函式的定義方式來呼叫並取的特定的物件屬性
而在此 this
在物件的方法中調用是非常的常見
因此我們舉例一段程式碼
1 | var data = { |
在此我們可以看到 callName
是基於 data
這個物件底下呼叫的,因此 this
就會指向到 data
,所以 console.log(this.name)
就會出現 Ray
。
除此之外範例程式碼改成以下,結果也會是相同的
1 | function fn () { |
因此我們就可以得知,只要它在哪一個物件下呼叫那麼它就會指向到哪一個物件。
接下來這一段在額外調整一個範例程式碼
1 | function fn () { |
基本上 this
的重點觀念在於是在哪一個物件下呼叫的,那麼它會指向哪一個屬性,所以 data.callName();
是基於在 data
底下呼叫 callName
,因此就會是出現 Ray
,這邊前面觀念是完全一樣,而第二個 data.ming.callName();
的 callName
是基於在 ming
呼叫,因此 callName
就會指向到 ming
而出現 Ray2
。
接下來再來額外看一些不同的範例
1 | function fn () { |
在此我們會發現 callName
出來的結果會是 undefined
。
為什麼呢?剛剛有講到 this
的指向最主要與它怎麼呼叫有關係,因此我們將 data.callName
直接賦予到變數 a
中(注意這邊並沒有執行 callName
),因此 a
變數在呼叫時,是在 window
下呼叫,而此時的 window
並沒有 myName 這個屬性,因此就會是一個 undefined
。
這時候若調整成這樣就可以看到囉~
1 | var myName = 'JavaScript' |
透過該章節我們可以了解到,不管你怎麼定義函式 this
的指向終究只會與它的呼叫有關係而與它的定義方式沒有太大關聯。
最後再寫一個範例
1 | var myName = 'JavaScript' |
上面這一段程式碼,基本上在你輸入之後過一秒會發現 this
竟然會是出現 JavaScript
而不是 Ray
,而這邊最主要原因是出在與 this
的簡易呼叫有關係而導致 this
指向跑掉。