JavaScript中的this,迷人又淘氣

this是 JS 這門語(yǔ)言的魅力之一——靈活方便又難以捉摸,即使是有經(jīng)驗(yàn)的程序員,如果不仔細(xì)也有可能搞錯(cuò),關(guān)于this的用法也成為許多公司的經(jīng)典面試題。

如果你寫過(guò) Java ,你可能接觸過(guò)this——一般指向當(dāng)前對(duì)象,實(shí)際上,這時(shí)候this的含義已經(jīng)確定了,因?yàn)镴ava屬于編譯期綁定,而JS屬于運(yùn)行期綁定,所以導(dǎo)致this的含義在運(yùn)行過(guò)程中可能有多種變化。

進(jìn)一步說(shuō),this和它聲明環(huán)境無(wú)關(guān),而完全取決于他的執(zhí)行環(huán)境。務(wù)必牢記這句話。

//讀以下代碼之前,必須先閱讀《哈利·波特》原著。(笑)

var name = '羅恩';
var aaa = {
    name: '哈利',
    say: function () {
        console.log(this.name);
    }
}

var bbb = {
    name: '赫敏',
    say: aaa.say
}

var ccc = aaa.say;

aaa.say();    //哈利
bbb.say();    //赫敏
ccc();        //羅恩

我們看第一行,aaa.say()調(diào)用的是aaa對(duì)象本身的say()方法,此時(shí)this指代的是aaa對(duì)象本身,所以此時(shí)輸出當(dāng)然就是aaa對(duì)象的name屬性值。

第二行,bbb.say();輸出赫敏一定和JS新手們的常識(shí)不相符,其實(shí)只要牢記“this取決于執(zhí)行環(huán)境”就能想明白。bbb對(duì)象是怎么聲明自身的say方法的呢?它只是把a(bǔ)aa對(duì)象的say方法引用過(guò)來(lái),注意,引用的是一個(gè)方法而非一個(gè)對(duì)象,而aaa.say存儲(chǔ)的是一個(gè)匿名函數(shù),所以這種寫法和以下代碼并沒(méi)有什么區(qū)別。

var bbb = {
    name: '赫敏',
    say: function () {
        console.log(this.name);
    }
}

第三行的ccc()是在最外層執(zhí)行,也就是在全局對(duì)象window下。所以ccc()執(zhí)行的時(shí)候this指代的就是window對(duì)象。而在window對(duì)象下聲明了name屬性,就相當(dāng)于window.name = '羅恩',輸出的當(dāng)然就是羅恩。

當(dāng)然,也有特殊情況,那就是 setTimeout 和 setInterval 。
我把開頭的aaa對(duì)象的聲明改成:

var aaa = {
    name: '哈利',
    getName: function () {
        setTimeout(function(){
            console.log(this.name);
        },100)
    }
}

僅僅是在console.log(this.name)外面套了一個(gè)setTimeout,猜猜原來(lái)三行的輸出會(huì)是什么?

答案:3個(gè)羅恩。
也就是說(shuō),三次this,指代的都是window對(duì)象。

關(guān)于為什么會(huì)這樣,我這里暫時(shí)不詳細(xì)展開,因?yàn)樯婕暗?strong>JS異步回調(diào)的知識(shí),如果你僅僅想快速熟悉this的用法,那么只要記住這個(gè)特殊情況即可。這個(gè)知識(shí)點(diǎn)曾經(jīng)是阿里還是小米的面試題。

顯然,三個(gè)羅恩不是我想要的,畢竟韋斯萊夫人的孩子已經(jīng)夠多了。那么我們只需稍微改寫一下這個(gè)方法:

getName: function () {
        //在setTimeout外存儲(chǔ)this指代的對(duì)象
        var that = this;
        setTimeout(function(){
            //this.name變成了that.name
            console.log(that.name);
        },100)
    }

輸出就又正常了。

顯然,that并不是一個(gè)關(guān)鍵字,只是一個(gè)大家解決這種情況時(shí)約定俗成的名字。如果你愿意,也可以叫thatGuy。當(dāng)然,考慮到可能會(huì)有其他人維護(hù)你的代碼,還是用that比較好。

之所以寫這篇文章,是為了我下一篇文章做鋪墊:
《巧用JavaScript中apply()和call()》
敬請(qǐng)期待~~

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

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

  • 沒(méi)搞錯(cuò)吧!js寫了那么多年,this還是會(huì)搞錯(cuò)!沒(méi)搞錯(cuò),javascript就是回搞錯(cuò)! ………… 在寫java的...
    zhoulujun閱讀 1,497評(píng)論 0 11
  • 請(qǐng)移步:https://blog.cdswyda.com/post/20161019
    依韻宵音閱讀 660評(píng)論 5 19
  • 在初階段我看js中的時(shí)候簡(jiǎn)直就是一臉蒙B,跟現(xiàn)在的棒子國(guó)的女人一樣,看來(lái)看去都是一個(gè)樣,但是根本上還是不知道出自那...
    Ziksang閱讀 842評(píng)論 2 10
  • 無(wú)論新入行的開發(fā)者,還是老手,也時(shí)常會(huì)被關(guān)鍵詞“this”所迷惑。這篇文章的目標(biāo)就是全面地解釋this。當(dāng)你讀完這...
    Ryan57閱讀 919評(píng)論 0 5
  • 什么是天賦?所謂天賦就是指上天賦予你的才能。天賦與生俱來(lái),發(fā)揮和利用你的天賦是上天的旨意,就如同大自然賦予魚兒游泳...
    田妞1999閱讀 927評(píng)論 0 0

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