摘要:用偽代碼來表示函數(shù)未進(jìn)入執(zhí)行階段之前,變量對象中的屬性都不能訪問但是進(jìn)入執(zhí)行階段之后,變量對象轉(zhuǎn)變?yōu)榱嘶顒訉ο蟆H稚舷挛闹?,變量對象就是本身。函?shù)上下文中,變量對象包括函數(shù)聲明,變量聲明。
概述
JavaScript 的可執(zhí)行代碼,具有執(zhí)行上下文,而每個上下文包括以下 3 個屬性:
變量對象(variable object, 簡稱 VO)
作用域鏈(scope chain)
this
變量對象提供了當(dāng)前環(huán)境所需的變量和函數(shù)
作用域鏈用于保證 JS 中變量和函數(shù)有序地訪問
this 為函數(shù)提供了執(zhí)行者對象
一個上下文的執(zhí)行周期可以用下圖示意:
本文就來介紹執(zhí)行上下文中的變量對象。
那什么是變量對象呢?先看定義:
變量對象是與執(zhí)行上下文相關(guān)的數(shù)據(jù)作用域,用于存儲執(zhí)行上下文中的變量和函數(shù)聲明。
不同的執(zhí)行上下文,變量對象會有一些差別。接下來就分別針對不同的上下文討論其區(qū)別。
一、全局上下文全局對象(Global object) 是在進(jìn)入任何執(zhí)行上下文之前就已經(jīng)創(chuàng)建了的對象;
這個對象只存在一份,它的屬性在程序中任何地方都可以訪問,全局對象的生命周期終止于程序退出那一刻。
在全局代碼的上下文執(zhí)行環(huán)境中,變量對象就是全局對象,在瀏覽器中,就是 window 對象。
此時,我們可以用 this 和 self 來訪問到全局對象,也就是它本身
console.log(this) // window console.log(self) // window
其次,全局對象初始創(chuàng)建階段將 Math、String、Date、parseInt 等函數(shù)作為自身方法,還會把全局變量作為自己的屬性。
用偽代碼表示就是:
global = { Math: <...> Date: <...> window: global // 引用自身 }二、函數(shù)上下文
我們已經(jīng)知道,變量對象存儲量執(zhí)行上下文中的函數(shù)聲明和變量,在函數(shù)上下文中,多了 arguments(函數(shù)參數(shù)列表), 一個類數(shù)組對象。
用偽代碼來表示:
VO = { arguments: Arguments, variables: undefine, functionName:}
函數(shù)未進(jìn)入執(zhí)行階段之前,變量對象中的屬性都不能訪問!但是進(jìn)入執(zhí)行階段之后,變量對象轉(zhuǎn)變?yōu)榱嘶顒訉ο螅╝ctivation object)。
所以,在函數(shù)上下文中,我們將活動對象(activation object)作為變量對象,活動對象最開始只包含一個變量就是 arguments 對象(這個對象是全局環(huán)境中沒有的)。
arguments 的屬性值 Arguments 它包括如下屬性:
callee — 誰調(diào)用了本函數(shù)
length — 真正傳遞的參數(shù)個數(shù)
properties-indexes (字符串類型的整數(shù)) 屬性的值就是函數(shù)的參數(shù)值(按參數(shù)列表從左到右排列)
三、創(chuàng)建過程我們再一次來看這個過程圖:
創(chuàng)建階段
全局對象初始化的時候,就將變量對象引用了自身。
而函數(shù)的創(chuàng)建卻有需要注意的地方。
函數(shù)在創(chuàng)建階段就創(chuàng)建了變量對象
其中,變量對象包括:
當(dāng)前函數(shù)的參數(shù)列表,建立 Arguments 對象。
所有的函數(shù)聲明(不包括函數(shù)表達(dá)式哦!),直接指向函數(shù)
所有的變量聲明(var 聲明的變量),默認(rèn)為 undefined
進(jìn)入執(zhí)行上下文時,函數(shù)聲明和變量聲明都會提前,這就是聲明提升,但是變量聲明的值都是undefined,而函數(shù)聲明的變量已經(jīng)可以指向函數(shù)。變量聲明的優(yōu)先級最低。
看下面這段代碼:
function foo(a, b) { var c = 10; function d() {} var e = function _e() {}; (function x() {}); } foo(10);
當(dāng)進(jìn)入函數(shù) foo 時,其變量對象的表現(xiàn)形式為:
VO = { arguments: { 0: 10, 1: undefined, length: 1 } c: undefined, d:, e: undefined, }
x 是函數(shù)表達(dá)式,所以不在變量對象當(dāng)中,e 變量引用的值也是函數(shù)表達(dá)式,所以變量 e 本身是聲明,所以在變量對象當(dāng)中。
執(zhí)行階段
當(dāng)前進(jìn)入執(zhí)行階段,變量對象激活成活動對象,函數(shù)會順序執(zhí)行代碼,改變變量對象的值:
以上代碼就變成:
AO = { arguments: { 0: 10, 1: undefined, length: 1 } c: 10, d:, e: , }
接下來看一段代碼:
console.log(foo); function foo() { console.log("123") } var foo = "456";
以上會打印函數(shù),是因為:
變量優(yōu)先處理函數(shù)聲明,再是變量聲明。
再看一段代碼:
if (true) { var a = 1; } else { var b = 2; } console.log(a); // 1 console.log(b); // undefined
雖然 else 中的代碼永遠(yuǎn)不會被執(zhí)行,但是 b 的變量聲明在執(zhí)行之前就默認(rèn)被設(shè)置成 undefined了。
總結(jié)執(zhí)行上下文包括三個屬性,變量對象,作用域鏈,this, 不同的執(zhí)行上下文,變量對象是有區(qū)別的。
全局上下文中,變量對象就是本身。
函數(shù)上下文中,變量對象包括:arguments, 函數(shù)聲明,變量聲明。在函數(shù)創(chuàng)建階段,變量對象有默認(rèn)值,進(jìn)入執(zhí)行階段后,變量對象會被激活成活動對象,然后變量對象的值被順序改變。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/98411.html
摘要:對象數(shù)組初始化表達(dá)式,闖關(guān)記之上文檔對象模型是針對和文檔的一個。闖關(guān)記之?dāng)?shù)組數(shù)組是值的有序集合。數(shù)組是動態(tài)的,根闖關(guān)記之語法的語法大量借鑒了及其他類語言如和的語法。 《JavaScript 闖關(guān)記》之 DOM(下) Element 類型 除了 Document 類型之外,Element 類型就要算是 Web 編程中最常用的類型了。Element 類型用于表現(xiàn) XML 或 HTML 元素...
摘要:下面,讓我們以一個函數(shù)的創(chuàng)建和激活兩個時期來講解作用域鏈?zhǔn)侨绾蝿?chuàng)建和變化的。這時候執(zhí)行上下文的作用域鏈,我們命名為至此,作用域鏈創(chuàng)建完畢。 JavaScript深入系列第五篇,講述作用鏈的創(chuàng)建過程,最后結(jié)合著變量對象,執(zhí)行上下文棧,讓我們一起捋一捋函數(shù)創(chuàng)建和執(zhí)行的過程中到底發(fā)生了什么? 前言 在《JavaScript深入之執(zhí)行上下文?!分兄v到,當(dāng)JavaScript代碼執(zhí)行一段可執(zhí)行代...
摘要:深入系列第四篇,具體講解執(zhí)行上下文中的變量對象與活動對象。下一篇文章深入之作用域鏈本文相關(guān)鏈接深入之執(zhí)行上下文棧深入系列深入系列目錄地址。 JavaScript深入系列第四篇,具體講解執(zhí)行上下文中的變量對象與活動對象。全局上下文下的變量對象是什么?函數(shù)上下文下的活動對象是如何分析和執(zhí)行的?還有兩個思考題幫你加深印象,快來看看吧! 前言 在上篇《JavaScript深入之執(zhí)行上下文?!分?..
摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進(jìn)階計劃,點擊查看前端進(jìn)階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計劃一共28期,每期...
摘要:深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧變量對象作用域鏈?zhǔn)侨绾巫兓?。前言在深入之?zhí)行上下文棧中講到,當(dāng)代碼執(zhí)行一段可執(zhí)行代碼時,會創(chuàng)建對應(yīng)的執(zhí)行上下文。 JavaScript深入系列第七篇,結(jié)合之前所講的四篇文章,以權(quán)威指南的demo為例,具體講解當(dāng)函數(shù)執(zhí)行的時候,執(zhí)行上下文棧、變量對象、作用域鏈?zhǔn)侨绾巫兓摹?前言 在《Jav...
摘要:引子前不久我建立的技術(shù)群里一位問了一個這樣的問題,她貼出的代碼如下所示執(zhí)行結(jié)果如下所示第一個第二個這是一個令人詫異的結(jié)果,為什么第一個彈出框顯示的是,而不是呢這種疑惑的原理我描述如下一個頁面里直接定義在標(biāo)簽下的變量是全局變量即屬于對象的變量 1) 引子 前不久我建立的技術(shù)群里一位MM問了一個這樣的問題,她貼出的代碼如下所示: var a = 1; function hehe...
閱讀 2298·2021-11-24 09:38
閱讀 2073·2021-11-22 14:44
閱讀 1156·2021-07-29 13:48
閱讀 2621·2019-08-29 13:20
閱讀 1119·2019-08-29 11:08
閱讀 2060·2019-08-26 10:58
閱讀 1267·2019-08-26 10:55
閱讀 3161·2019-08-26 10:39