javascript中的this原理

    var obj = {
        foo: function() {console.log(this.bar)};
        bar: 1
    }
    var foo = obj.foo;
    var bar = 2;
    obj.foo(); // 1
    foo();// 2

上面這段代碼中,obj.foo 和foo指向的是同一個(gè)函數(shù),但是結(jié)果卻是不一樣的。

我們都知道,javascript中,this指的是函數(shù)運(yùn)行時(shí)所在的環(huán)境,obj.foo()運(yùn)行在obj環(huán)境,所以this指向的是obj;foo()運(yùn)行在全局環(huán)境,所以this指向全局環(huán)境。但是為什么就說(shuō)obj.foo()是在obj環(huán)境執(zhí)行,而一旦var foo = obj.foo,foo()就變成了全局環(huán)境執(zhí)行呢?也就是說(shuō)函數(shù)的運(yùn)行環(huán)境到底是由什么決定的。對(duì)于這個(gè)問(wèn)題,我們往往是模棱兩可的,下面就來(lái)解釋下javascript這樣處理的原理,本文主要參考了阮一峰老師的文章JavaScript 的 this 原理。

內(nèi)存的數(shù)據(jù)結(jié)構(gòu)

  • var obj = {foo: 5} 我們把一個(gè)對(duì)象賦值給了一個(gè)變量obj。javascript引擎會(huì)先在內(nèi)存里面,生成一個(gè)對(duì)象{foo: 5},然后把這個(gè)對(duì)象的內(nèi)存地址賦值給obj。這也就是說(shuō)obj實(shí)際上是一個(gè)地址,后面如果要讀取obj.foo,引擎會(huì)先從obj拿到內(nèi)存地址,然后再?gòu)脑摰刂纷x出原始的對(duì)象,返回它的foo屬性。

    原始的對(duì)象以字典結(jié)構(gòu)保存,每一個(gè)屬性名都對(duì)象一個(gè)屬性描述對(duì)象,例如上述foo屬性實(shí)際上是以下面形式保存的。


    image

    注意,foo屬性的值保存在屬性描述對(duì)象的value屬性里面

函數(shù)

  • 如果屬性的值是一個(gè)函數(shù),例如 var obj = {foo:function(){}},這時(shí),引擎會(huì)將函數(shù)單獨(dú)保存在內(nèi)存中,然后再將函數(shù)的地址賦值給foo屬性的value屬性


    image

由于函數(shù)是一個(gè)單獨(dú)的值,所以它可以在不同的環(huán)境(上下文)執(zhí)行

    var f = function() {}
    var obj = {f: f}
    // 單獨(dú)執(zhí)行
    f();
    // obj 環(huán)境執(zhí)行
    obj.f();

環(huán)境變量

javascript允許在函數(shù)體內(nèi)部,引用當(dāng)前環(huán)境的其他變量

    var f = function() {
        console.log(x);
    }

上面代碼中,函數(shù)體里面使用了變量x,該變量是由運(yùn)行環(huán)境提供的。由于函數(shù)可以在不同的運(yùn)行環(huán)境中執(zhí)行,所以需要一種機(jī)制,能夠在函數(shù)體內(nèi)部獲得當(dāng)前的運(yùn)行環(huán)境,所以,this出現(xiàn)了,它的設(shè)計(jì)目的就是在函數(shù)體內(nèi)部,指代函數(shù)當(dāng)前的運(yùn)行環(huán)境。

    var f = function() {
        console.log(this.x)
    }

上面代碼中,函數(shù)體里面的this.x 就是當(dāng)前運(yùn)行環(huán)境的x

    var f = function() {
        console.log(this.x);
    }
    var x = 1;
    var obj = {
        f: f,
        x: 2
    }
    // 單獨(dú)執(zhí)行
    f(); // 1
    // obj環(huán)境執(zhí)行
    obj.f() // 2

上面代碼中,函數(shù)f在全局執(zhí)行,this.x指向全局環(huán)境x


image

在obj環(huán)境執(zhí)行,this.x指向obj.x


image

回到文章開頭的問(wèn)題,obj.foo()是通過(guò)obj找到foo,所以就是在obj環(huán)境執(zhí)行,一旦var foo = obj.foo,變量就直接指向函數(shù)本身,所以foo()就變成在全局環(huán)境執(zhí)行。

?著作權(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)容

  • 第2章 基本語(yǔ)法 2.1 概述 基本句法和變量 語(yǔ)句 JavaScript程序的執(zhí)行單位為行(line),也就是一...
    悟名先生閱讀 4,535評(píng)論 0 13
  • Spring Cloud為開發(fā)人員提供了快速構(gòu)建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務(wù)發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,534評(píng)論 19 139
  • 函數(shù)和對(duì)象 1、函數(shù) 1.1 函數(shù)概述 函數(shù)對(duì)于任何一門語(yǔ)言來(lái)說(shuō)都是核心的概念。通過(guò)函數(shù)可以封裝任意多條語(yǔ)句,而且...
    道無(wú)虛閱讀 4,943評(píng)論 0 5
  • Javascript 中的 this,有時(shí)候讓人迷惑,所以總結(jié)了一下關(guān)于this指向的問(wèn)題。 在函數(shù)中 this ...
    lxt410725閱讀 489評(píng)論 0 1
  • 原文/vivi薇薇 轉(zhuǎn)載時(shí)請(qǐng)務(wù)必備注作者姓名 閨蜜,一個(gè)在陜西工作的異鄉(xiāng)人,從她那里,我能夠深深地感覺(jué)到:如果你在...
    于冰者之夏蟲閱讀 1,571評(píng)論 10 16

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