js 中的 this

要選出 js 中最讓初學(xué)者最頭疼的概念, this 必定占其中的前 3 名。不像 cpp, java 或者 python,js 在任意函數(shù)中都能使用 this。并其 this 在 js 中更類似于動(dòng)態(tài)作用域。即 this 并不是在定義時(shí)決定,而是在函數(shù)調(diào)用時(shí)才決定。這種決定綁定到哪個(gè) this 的行為稱為 this 綁定。例如通過一個(gè)普通函數(shù)調(diào)用時(shí),this 實(shí)際上是綁定到全局對象(瀏覽器環(huán)境為 window,node 環(huán)境為 global):

function bar(){
  this.a = 1;
}
bar()
console.info(global.a)

默認(rèn)綁定

默認(rèn)綁定是指通過調(diào)用普通函數(shù)的方式進(jìn)行綁定,也就是上文提到的綁定方式:

function bar(){
  this.a = 1;
}
bar()
console.info(global.a) //1

隱式綁定

隱式綁定是指該函數(shù)通過對象的成員函數(shù)的方式調(diào)用,此時(shí) this 會(huì)綁定到調(diào)用的對象。例如:

global.a = 1
obj = {
    a: 2,
    bar: function(){
        console.info(this.a)
    }
}
obj.bar() // 2

注意要強(qiáng)調(diào)的一點(diǎn)是,this 綁定始終只和調(diào)用方式有關(guān),而和定義的方式無關(guān),例如:

global.a = 1
function bar(){
    console.info(this.a)
}
obj = {
    a: 2
}
obj.bar = bar
obj.bar() // 2

雖然 bar 定義在全局環(huán)境中,但仍然綁定到 obj 而不是全局對象。

隱式綁定丟失

由于綁定只和調(diào)用有關(guān),因此如果一個(gè)成員函數(shù)通過普通函數(shù)的調(diào)用方式進(jìn)行調(diào)用,那么它 this 就會(huì)綁定到全局變量,例如:

global.a = 1
obj = {
    a: 2,
    bar: function(){
        console.info(this.a)
    }
}
const bar = obj.bar
bar() // 1

可以看出,此時(shí) this 綁定到了全局對象。還有一種更不容易發(fā)現(xiàn)的情況,即將成員函數(shù)當(dāng)成回調(diào)函數(shù)使用,由于存在一種類似的賦值行為,也會(huì)產(chǎn)生對應(yīng)的丟失問題,例如:

var a = 1
obj = {
    a: 2,
    bar: function(){
        console.info(this.a)
    }
}
setInterval(obj.bar, 1000) // 1 1 1 1 1

這就能解釋為什么在 react 中需要手動(dòng)綁定 this。

顯式綁定

通過 call 或者 apply 能夠顯示的綁定對象到 this:

function bar(){
    console.info(this.a)
}
bar.call({a: 1}) //1
bar.call({a: 2}) //2

硬綁定

為了避免在傳遞回調(diào)函數(shù)的時(shí)候丟失 this 綁定,我們可以采用一種稱為硬綁定的方式,例如:

obj = {
    a: 1,
    bar: function(){
        console.info(this.a)
    }
}
function bind(bar, obj){
    function inner(){
        return bar.call(obj)
    }
    return inner
}
foo = bind(obj.bar, obj)
setInterval(foo, 1000)

通過實(shí)現(xiàn)一個(gè) bind 輔組函數(shù)來進(jìn)行綁定。此時(shí),就算我們將其作為一個(gè)回調(diào)函數(shù)也不會(huì)丟失 this 綁定。由于這種場景非常常見,所以 js 內(nèi)置了 Function.prototype.bind 來實(shí)現(xiàn)硬綁定。有的同學(xué)突發(fā)奇想,如果我們將一個(gè)硬綁定的函數(shù)再賦值給一個(gè)對象:

obj = {
    a: 1,
    bar: function(){
        console.info(this.a)
    }
}
obj.foo = obj.bar.bind({a: 3})
obj.foo() //3

可以看出,仍然綁定到 {a: 3} 而不是 obj。所以優(yōu)先級硬綁定 > 隱式綁定。

new 綁定

當(dāng)一個(gè)函數(shù)作為構(gòu)造函數(shù)使用時(shí),它會(huì)綁定到它創(chuàng)建的對象上,例如:

function bar(){
    this.a = 1
}
const b = new bar()
console.info(b.a) // 1
console.info(global.a) // undefined
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 目錄this 是什么this 的四種綁定規(guī)則綁定規(guī)則的優(yōu)先級綁定例外擴(kuò)展:箭頭函數(shù)this 是什么理解this之前...
    18372a74d8b8閱讀 551評論 0 1
  • 最近在看《你不知道的JavaScript(上卷)》,覺得書中關(guān)于this的知識點(diǎn)講解的比較透徹易懂,在此做一些整理...
    jeff_nz閱讀 677評論 0 0
  • 1. 為什么要用this? this是js中最為復(fù)雜的機(jī)制之一。大部分開發(fā)者寫了很久的js代碼都可能沒有主動(dòng)使用過...
    knowjs閱讀 409評論 0 1
  • 摘要:本文屬于原創(chuàng),歡迎轉(zhuǎn)載,轉(zhuǎn)載請保留出處:https://github.com/jasonGeng88/blo...
    Camilia_yang閱讀 396評論 0 0
  • 前言 近期對this很感興趣,于是乎簡單整理了一些關(guān)于this的技術(shù)點(diǎn),加深一下對this的理解。 非箭頭函數(shù) 在...
    little_short閱讀 570評論 0 0

友情鏈接更多精彩內(nèi)容