什麼是this
this
是 JavaScript 的一個關鍵字。this
是 function 執行時,自動生成的一個內部物件。- 隨著 function 執行場合的不同,
this
所指向的值,也會有所不同。 - 在大多數的情況下,this 會因為 function 的呼叫方式而有所不同。
JavaScipt 的 this
JavaScript 的 this
跟其他程式語言慣用的那個 this
有了差異,這就是為什麼 this
往往不容易弄懂的原因。
儘管 this
的定義不太一樣,但我認為本質上還是很類似的。
this
的值跟作用域跟程式碼的位置在哪裡完全無關,只跟「你如何呼叫」有關
舉個例子
1 | var obj = { |
請解釋最後兩個呼叫function的值為什麼不一樣。
呼叫 Function
首先需要從呼叫function
開始說起
JavaScript(ES5)裡面有有三種呼叫function
的方法:
1 | func(p1, p2) |
一般來說常見的都是前兩種方法,而且普遍認為前兩種方法「優於」第三種方法。
從看到這文章起,你一定要記住第三種呼叫方法,才是正常呼叫用法:
1 | func.call(context, p1, p2) |
其他兩種都是Syntactic suga
,可以等價轉換為 call
:
1 | func(p1, p2) 等於 |
(我稱為「轉換程式碼」,方便下文引用)
至此 function
呼叫只有一種方法:
1 | func.call(context, p1, p2) |
這樣,this 就好解釋了
this
,就是上面程式碼中的 context
。就這麼簡單。
this
是你 call
一個 function
時傳的 context
,由於你從來不會使用 call
方法的 function
呼叫,所以你一直不知道。
先看 func(p1, p2) 中的 this 如何定義
當寫以下程式碼時
1 | function func(){ |
按理來說 print
出来的 this
應該是 undefined 了吧,但是瀏覽器中有條規則:
如果你傳的 context
是 null
或 undefined
,那麼 window
就是默認的 context
此外 use strict
下默認 context
是 undefined
,因此上面的 print
結果是 window
。
如果你希望這的 this
不是 window
,很簡單:
1 | func.call(obj) // 那這裡面的 this 就是 obj 了 |
再看 obj.child.method(p1, p2) 的 this 如何定義
1 | var obj = { |
回到最一開始的例子
1 | var obj = { |
[ ] 語法
1 | function fn (){ console.log(this) } |
可以把 arr[0]( )
想像成arr.0( )
,雖然後者的語法跑起來會報錯,但是方法與轉換程式碼中的 obj.child.method(p1, p2)
對應上了,於是就可以只接把它轉換成了:
1 | arr[0]() |
Arrow Function
實際上 Arrow Fucntion
裡面並沒有 this
,如果在 Arrow Function
看到 this
,可以直接把它當成 Arrow Function
外面的 this
即可。外面的 this
是什麼,Arrow Function
裡面的 this
就是什麼,因為 Arrow Function
本身不支援 this
。
有人說「Arrow Function 裡面的 this 指向 Arrow Function 外面的 this」,這聽起來很傻,因為Arrow Function 内外 this 就是同一個東西,并沒有存在什麼指向不指向。
總結
this
就是你 call
一個 Function
時,傳入的第一個參數。(請務必記下來「this
就是 call
的第一個參數」)
如果你的呼叫Function
方法不是 call
,請想想「轉換程式碼」將它轉乘 call
方法也許就能想情楚了。