JS中的變量對(duì)象

變量對(duì)象

關(guān)鍵字

變量對(duì)象(variable object), 活動(dòng)對(duì)象(activation object), 執(zhí)行上下文

變量對(duì)象(variable object)

作用:

每個(gè)執(zhí)行上下文都有一個(gè)與之關(guān)聯(lián)的變量對(duì)象, 執(zhí)行上下文中定義的所有變量和函數(shù)都保存在這個(gè)對(duì)象中, 我們無法編碼無法訪問這個(gè)對(duì)象,但是解析器會(huì)在后臺(tái)處理它。

執(zhí)行上下文一章中我們提到一個(gè)執(zhí)行上下文必定包括:變量對(duì)象,作用域鏈,this對(duì)象, 執(zhí)行上下文又分三種全局上下文,函數(shù)上下文,eval上下文。

全局上下文

一句話:在全局上下文中的變量對(duì)象就是宿主環(huán)境的全局對(duì)象。
宿主環(huán)境?說的簡(jiǎn)單點(diǎn)兒就是:瀏覽器或者nodejs等
瀏覽器中全局對(duì)象就是window對(duì)象??梢园聪翭12輸入this驗(yàn)證。在nodejs中全局對(duì)象就是global。

函數(shù)上下文

說起函數(shù)上下文就不得不先說到活動(dòng)對(duì)象

活動(dòng)對(duì)象(activation object)

活動(dòng)對(duì)象在最開始時(shí)只包含一個(gè)變量, 那就是arguments對(duì)象(此對(duì)象在全局上下文中是不存在的)。 如果當(dāng)前上下文時(shí)函數(shù)上下文,那就將活動(dòng)對(duì)象轉(zhuǎn)變尾變量對(duì)象。

活動(dòng)對(duì)象與變量對(duì)象的區(qū)別

未進(jìn)入執(zhí)行階段之前,變量對(duì)象(VO)中的屬性都不能訪問!但是進(jìn)入執(zhí)行階段之后,變量對(duì)象(VO)轉(zhuǎn)變?yōu)榱嘶顒?dòng)對(duì)象(AO),里面的屬性都能被訪問了,然后開始進(jìn)行執(zhí)行階段的操作。它們其實(shí)都是同一個(gè)對(duì)象,只是處于執(zhí)行上下文的不同生命周期。

執(zhí)行上下文創(chuàng)建階段中的變量對(duì)象

既然執(zhí)行上下文包括了三個(gè)屬性,那肯定要確定自己的屬性包括了哪些東西吧。本文先看看變量對(duì)象屬性。
此時(shí)并沒有執(zhí)行代碼,只是進(jìn)入了執(zhí)行上下文。
變量對(duì)象包含了:

  1. 函數(shù)的所有形參
    • 由參數(shù)名及起對(duì)應(yīng)值組成一個(gè)變量對(duì)象的屬性被創(chuàng)建
    • 如果沒有實(shí)參,則值為undefined
  2. 函數(shù)的聲明
    • 由函數(shù)稱和對(duì)應(yīng)值(函數(shù)對(duì)象(function-object))組成一個(gè)變量對(duì)象的屬性被創(chuàng)建
    • 如果已經(jīng)存在相同名稱的屬性,則完全替換這個(gè)屬性
  3. 變量的聲明
    • 由名稱和對(duì)應(yīng)值(undefined)組成一個(gè)變量對(duì)象的屬性被創(chuàng)建
    • 如果變量名稱跟已經(jīng)聲明的形式參數(shù)或函數(shù)相同,則變量聲明不會(huì)干擾已經(jīng)存在的這類屬性。

舉個(gè)例子

function foo(a) {
  var b = 'b',
  var c = function () {console.log(c)}
  function d() {console.log('d')}
}

foo('a')

創(chuàng)建階段

此時(shí)的VO(變量對(duì)象)是:

VO: {
    arguments: {
      0: 'a',
      length: 1
    },
    b: undefined
    c: undefined
    d: -> function d() {console.log('d')}
}

執(zhí)行階段

代碼從上至下順序執(zhí)行, VO中的屬性逐漸被賦值
此階段為

VO: {
    arguments: {
      0: 'a',
      length: 1
    },
    b: 'b'
    c: -> function () {console.log('c')}
    d: -> function d() {console.log('d')}
}

其實(shí)這也從變量對(duì)象的角度出發(fā)理解了javascript中的函數(shù)提升以及變量提升。

console.log(foo) // 會(huì)打印函數(shù)foo

function foo() {}

var foo = 1

這個(gè)例子中因?yàn)?strong>函數(shù)提升以及變量提升的原因其實(shí)正確的執(zhí)行步驟應(yīng)該如下:

function foo() {} // 函數(shù)提升
// var foo = undefined // 變量提升
// 注釋掉的原因是因?yàn)槊Q
// 相同,根據(jù)變量聲明的規(guī)則,若變量名與形參名
// 或函數(shù)名重復(fù)時(shí),并不會(huì)干擾或覆蓋。

console.log(foo) 
foo = 1

在函數(shù)執(zhí)行上下文的創(chuàng)建階段

VO: {
  arguments: {
    length: 0
  },
  foo: -> function foo() {}
}

進(jìn)入執(zhí)行階段后會(huì)根據(jù)代碼依次賦值。這就是js中函數(shù)提升變量提升產(chǎn)生的原因。

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

  • 函數(shù)參數(shù)傳遞的過程實(shí)際上就是實(shí)參像形參復(fù)制值的過程。 在向參數(shù)傳遞基本類型的值時(shí),被傳遞(實(shí)參)的值會(huì)復(fù)制給一個(gè)局...
    小小的白菜閱讀 476評(píng)論 0 1
  • 來源:仗劍走天涯! 關(guān)于javascript的作用域的一些總結(jié),主要參考以上文章,加上自己的整理的理解。 近日對(duì)j...
    Michael_林閱讀 1,020評(píng)論 0 1
  • 上一節(jié)我們討論了執(zhí)行上下文,那么在上下文中到底有什么內(nèi)容,為什么它會(huì)和作用域鏈扯上關(guān)系,JS 解釋器又是怎么找到我...
    liuxuan閱讀 631評(píng)論 0 3
  • 應(yīng)酬的時(shí)候我看到我的狗站在窗外看著我,我跑出去摸了摸它問它你怎么來了?我沒事干過來看看你??茨阃﹂_心的就不想打擾你...
    北板藍(lán)根閱讀 332評(píng)論 0 0
  • 來到雅安第二天了,記得來的路上,姐姐一直在給我說這邊的山水和老家的有大不一樣,稍加描述了一番,便也勾起了我的好奇心...
    小峙閱讀 321評(píng)論 2 5

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