this
在函式中,主要是看誰呼叫這個函式
。
this 的四套規則:
- 預設繫結
- 隱含的繫結
- 明確的繫結
- new 繫結
預設 binding
預設繫結為 global object,當其他規則都不符合的時候
就會使用此規則
1 | function foo() { |
如果使用 const a = 'global object';
,則會印出 undefined
,因為 const
並不會讓 a 掛在 global object 下, 如果使用 window.a = 'global object'
,結果則和 var
一樣。
使用嚴格模式 use strict
則會得到 TypeError
。
隱含的 binding
是否有一個物件去 call 那個 function
1 | function foo() { |
使用 callback 的方式呼叫,也會因為呼叫的地點而將繫結斷開。
如下所示, printA 已經不是被 obj 所呼叫,
因此一樣使用預設繫結。
1 | function printA() { |
隱含的失去
因為呼叫是 bar
呼叫 obj 內的 printA
,(行為委派)
因此採用的是 global 下的 global object
,而不是印出 2 。
1 | function printA() { |
由於是 bar()
呼叫了 fn printA
所以,是一個普通的呼叫,使用了預設繫結
明確的 binding
使用 call()
、 apply()
、 bind()
call()
使用 call()
, this 會指定在物件上(有給第一個參數)(改變 this 指向)
將 this
綁定 obj,在函式 bar 讓 this
明確的綁住 obj ,不管怎麼控制 bar 的綁定, this
都會是 obj。
1 | function foo() { |
apply()
apply()
跟 call()
大致上雷同,唯一不同是 call()
可以接受一連串的參數, apply()
則接受一組陣列形式的參數。
bind()
bind()
會回傳一個 function,而這個 function, 經過處理, this 已經被綁定在指定的 obj 上。
1 | function foo() { |
由於 bind()
return 一個 function,因此如果有參數,可以在 bar()
再帶參數。
如下,可以想成加工(強制 this 綁定在 obj)後的 addToThis
1 | obj = { |
new binding
無論是 function constructor 或 classes ,
使用 new 會創造出一個全新的物件, this 即指向這個物件。
1 | function People(name) { |
reference
You Don’t know JS: Scope & Closure, this & Prototypes