JS 中的this到底是什么
首先說結論:
fn.call (context,argument[]) ,this 就是你 call 一個函數時,傳入的 context。
那大家肯定有疑問,函數調用形式多鐘,如果不是這種調用形式呢?那又如何確定this呢?
接下來我們先從函數調用形式說起
函數調用形式
JS(ES5)里面有三種函數調用形式:
fn(p1, p2)
obj.child.method(p1, p2)
fn.call(context, p1, p2) //標準調用形式
其中,第三種調用形式,才是正常調用形式函數調用標準形式
fn.call(context, p1, p2)
其他兩種都是語法糖,可以等價地變為 call 形式:
fn(p1, p2) 等價于
fn.call(undefined, p1, p2)
obj.child.method(p1, p2) 等價于
obj.child.method.call(obj.child, p1, p2)
所以,我們知道不論哪種情況的函數調用,都可以轉換為標準形式:
fn.call(context, p1, p2)
如此,只要是函數調用,你就可以輕松的知道this的傳入形式。如果你的函數調用形式不是 call 形式,請按照「轉換代碼」將其轉換為 call 形式。
this 傳入的是什么?
在了解this 就是 call 一個函數時,傳入的 context后,我們還需要了解他傳入的是什么
首先我們構造一個監聽函數
$div.on('click',function(){
conlose.log('click')
conlose.log('this')
})
click
<div></div>
在這個監聽函數中,我們發現,打印出this就是我們監聽的元素
那么this是否就是這個監聽元素嗎?實際不是這樣的
接下來我們繼續構造一個事件委托
$div.on('click','button',function(){
conlose.log('click')
conlose.log('this')
})
click
<button></button>
在這個事件委托中,打印出的this是我們點擊的元素(button),并不是我們監聽的元素
那么現在結論出來了,this ===e.currentTaget ?
$div.on('click','button',function(e){
conlose.log('click')
if (this === e.currentTaget){
conlose.log('true')
}
})
click
true
實際證明,的確如此。
通常性看來,this 在JS中是多余的,它只是為了看起來像Java而設定的
this的使用方式
在一個對象里, 可以用this表示一個對象
通常時候,其實this是多余的,我們可以直接用對象名,而不使用this。
但是,某些時候,我們并不知道對象名,這時候就不得不用this來替代了。
let module = {
element: null,
init: function(){
let $div = this.element //this.element = module.element
//在這里,對象名module可以用this替代
$div.on('click','button',this.onClickButton)
$div.on('click',function(){
conlose.log('click')
})
},
onClickButton: function(e){
console.log('button is click')
}
}
module.init($div) // 等同于 module.init.call(module,$div)
但是 this在一個對象中,是可以改變的
let module = {
element: null,
init: function(){
let $div = this.element
$div.on('click','button',this.onClickButton) //這里的this === module
},
onClickButton: function(e){
console.log('button is click')
console.log('this') //由于觸發了click監聽事件,這里的this已經變成了監聽事件的點擊元素button
}
}
module.init($div) // 等同于 module.init.call(module,$div)
上例中,由于監聽事件的this的值是指向觸發事件的元素。所以this已經改變
可以看出,this在特定場景下,是會根據API的源代碼定義所改變。
那么如果我們想指定監聽事件傳入的this是我們想要的this,怎么辦?
$div.on('click','button',function(){
module.onClickButton.call(module,e) //這里我們強制指定了傳入this值為module
})
$div.on('click','button',this.onClickButton.bind(this))
我們還可以用bind
來實現
$div.on('click','button',this.onClickButton.bind(this))
總結
- this 就是你 call 一個函數時,傳入的 context
- 如果函數調用形式不是 call 形式,請將其轉換為 call 形式
- 在一個對象里, 可以用this表示一個對象
- 在監聽事件里,this的值是指向觸發事件的元素
- 任何函數都可以強制指定傳入的this,也可以使用bind來改變默認傳入this