在沒有意義的地方呼叫 this,預設值會是什麼?
this
的值取決於在什麼環境,依據環境不同,this
值也會不同
在 node.js 的 this
預設值會是 global
在瀏覽器上跑的話,this
會是 Window
但在嚴格模式,也就是設定 use strict
,this
的預設值會是 undefined
'use strict'; // 開啟嚴格模式
function test() {
console.log(this); // undefined
}
test();
DOM 元素中的 this
這邊的 this
就會是你實際做操作的東西,比如說用 click
,那 this
就是你點到哪個按鈕就是哪個按鈕
document.querySelector('.btn').addEventListener('click', function() {
console.log(this)
})
另外兩種呼叫 function 的方法:call 與 apply
前一篇文章有提到在模擬 new 背後在做的事情,有用到 call
這個 function
第一個參數傳的是什麼,this
就是什麼
'use strict';
function test() {
console.log(this);
}
test.call(123); // 123
test.call({}); // {}
test.call([1]); // [ 1 ]
除了 .call()
還有 .apply()
和 .call()
一樣第一個參數就是 this
的值
那和 .call()
差異在哪 ?
差異在於 .apply() 第二個參數會是 array
function test(a, b, c) {
console.log(this)
console.log(a, b, c)
}
test.call(123, 1, 2, 3)
test.apply(123, [1, 2, 3])
this
只有在跟物件導向扯上關係的時候,this
才有意義,在這關係以外基本上沒什麼意義this
在程式碼的哪邊無關,跟怎麼被呼叫有關
const obj = {
a: 123,
test: function(){
console.log(this)
}
}
obj.test()
上面程式碼的 this
是 obj 本身
const obj = {
a: 123,
test: function(){
console.log(this)
}
}
var func = obj.test
func() // obj.test()
上面程式碼的 this
的值變成 undefined
不是同一個 function 嗎? 怎麼值就不一樣了
所以這就是前面提到的 this
在程式碼的哪邊無關,跟怎麼被呼叫有關
上述例子可以用不同角度來看會比較好理解
首先 obj.test()
可以看成 obj.test.call(obj)
假設裡面還有一層 inner
const obj = {
a: 123,
inner: {
test: function(){
console.log(this)
}
}
}
obj.inner.test() // 可以看成 obj.inner.test.call(obj.inner)
// 上面這樣執行, this 都是 inner 這個物件
const func = obj.inner.test
func()
// 上面這樣執行, this 就會是 undefined
// 所以 func() 可以看成 func.call(undefined)
因為 func()
前面沒有其他東西,在 .call
可以看成傳 undefined 進去
而前面 obj.inner.test()
,test 前面還有 obj.inner. 所以在 .call
就是傳前面東西進去 obj.inner.test.call(obj.inner)
做個小測驗來了解對 this 熟不熟
'use strict';
function log() {
console.log(this);
}
var a = { a: 1, log: log };
var b = { a: 2, log: log };
log();
a.log();
b.log.apply(a)
答案
'use strict';
function log() {
console.log(this);
}
var a = { a: 1, log: log };
var b = { a: 2, log: log };
log(); // undefined
a.log(); // {a: 1, log: [Function: log] }
b.log.apply(a) // {a: 1, log: [Function: log] }
綁定 this 的值,用 .bind()
.bind()
會直接回傳一個 function
.call()
或 .apply()
會直接呼叫 function
用 .bind()
後即便再加 .call()
或 .apply()
都無法去改變 this 的值
const obj = {
a: 1,
test: function() {
console.log(this)
}
}
const bindTest = obj.test.bind('abc')
bindTest() // this 值是 abc
bindTest.call(123) // this 值還是 abc
arrow function 的 this
class Test{
run() {
console.log('run this:', this) // run this: Test {}
setTimeout(function() {
console.log(this) // 瀏覽器是 Window,嚴格模式下是 undefined
}, 100)
}
}
const t = new Test()
t.run()
但對於箭頭函式事情就變得不一樣
class Test{
run() {
console.log('run this:', this) // run this: Test {}
setTimeout(() => {
console.log(this) // Test {}
}, 100)
}
}
const t = new Test()
t.run()