摘要:根據(jù)順序我們也可以看出來,想要理解作用域鏈,執(zhí)行上下文是我們碰到的第一個坎。
在我們前面理解了作用域之后,“作用域鏈”這個概念就產(chǎn)生了。那么作用域鏈是什么意思,它又是怎么形成的,跟哪些概念有關(guān)系,這就是我接下來幾章想和大家探討的內(nèi)容:執(zhí)行上下文、變量對象和作用域鏈。根據(jù)順序我們也可以看出來,想要理解作用域鏈,執(zhí)行上下文是我們碰到的第一個坎。
這一章我們就來討論一下到底什么是執(zhí)行上下文。
1. 定義當 JS 引擎開始執(zhí)行預(yù)編譯生成的代碼時,就會進入到一個執(zhí)行上下文(Executable Code - 簡稱 EC)。
在 ECMA 標準規(guī)范里并沒有從技術(shù)角度去定義 EC 的具體類型和結(jié)構(gòu),這個是在實現(xiàn) ECMAScript 引擎時需要考慮的問題。
但是在邏輯上,我們可以將活動的執(zhí)行上下文看成一個棧結(jié)構(gòu)。棧底部永遠是全局上下文(global context),而頂部就是當前活動的執(zhí)行上下文。執(zhí)行到當前代碼時,上下文入棧,執(zhí)行完畢后,上下文出棧。
2. 可執(zhí)行代碼有幾種前面說到當引擎執(zhí)行到可執(zhí)行代碼的時候,就會將當前上下文壓入上下文棧中。那么可執(zhí)行的代碼又分為幾種?
在這里,我們先假設(shè)定義執(zhí)行上下文棧是一個數(shù)組:
</>復(fù)制代碼
EC = [];
第一種可執(zhí)行代碼 -- 全局代碼:
全局類型代碼是在加載外部的 js 文件或者本地 標簽中的代碼。
注意,在全局代碼中,并不包含定義在全局環(huán)境 function 內(nèi)的代碼。
程序啟動后進入初始化全局環(huán)境:
</>復(fù)制代碼
EC = [
globalContext
];
第二種可執(zhí)行代碼 -- 函數(shù)代碼:
當定義的函數(shù)被執(zhí)行時,就進入了函數(shù)代碼,當前函數(shù)上下文被壓入 EC 棧中。
注意,在函數(shù)代碼中,也不包含定義在該函數(shù)內(nèi)部環(huán)境 function 內(nèi)的代碼。
例如:
</>復(fù)制代碼
var a = 10;
function foo () {
var b = 20;
foo();
}
foo();
這個例子中的 EC 是什么樣子的呢?
</>復(fù)制代碼
// 初始化
EC = [
globalContext
];
// 第一次調(diào)用 foo 函數(shù)
EC = [
functionContext,
globalContext
];
// 在 foo 內(nèi)遞歸調(diào)用自己
EC = [
functionContext - recursively,
functionContext,
globalContext
];
// 繼續(xù)遞歸調(diào)用自己
EC = [
......
functionContext - recursively2,
functionContext - recursively,
functionContext,
globalContext
];
// 遞歸會不斷調(diào)用下去,因為沒有結(jié)束條件,所以這是一個死循環(huán)
// 所以,EC 只會不斷增加新的上下文,但是卻不會退出
只有每次 return 的時候,才會退出當前執(zhí)行上下文,相應(yīng)上下文會從棧中彈出,棧指針會自動移動位置。
注意,當函數(shù)沒有明確指明 return 什么的時候,默認 return undefined 。
如果有拋出的異常沒有被截獲的話,也有可能從一個或多個執(zhí)行上下文中退出。當所有代碼執(zhí)行完以后,EC 中只會包含全局上下文(global context),當程序退出以后,全局上下文也會退出。
第三種可執(zhí)行代碼 -- eval 代碼:
eval 函數(shù)在調(diào)用的時候會產(chǎn)生上下文。
例如:
</>復(fù)制代碼
eval("var a = 10");
(function foo () {
eval("var b = 20");
}());
alert(a); // 10
alert(b); // ReferenceError,b is not defined
這個例子中 EC 的變化如下:
</>復(fù)制代碼
// 初始化
EC = [
globalContext
];
// eval("var a = 10");
EC = [
evalContext,
globalContext
];
// eval 執(zhí)行完畢
EC = [
globalContext
];
// 立即執(zhí)行函數(shù) foo
EC = [
functionContext,
globalContext
];
// eval("var b = 20");
EC = [
evalContext,
functionContext,
globalContext
];
// eval 執(zhí)行完畢
EC = [
functionContext,
globalContext
];
// foo 執(zhí)行完畢
EC = [
globalContext
];
這就是一個典型的邏輯調(diào)用上下文棧。
在 setTimeout 和 setInterval 函數(shù)中的第一個參數(shù)也可以傳入代碼字符串,但是這個一般不會這么去用,所以這里也就不討論了。
3. 結(jié)論執(zhí)行上下文環(huán)境是我們了解變量對象和作用域鏈的基礎(chǔ),大家一定要好好理解(其實也并不難),下一節(jié)我們來討論變量對象,相信會讓大家有一定的收獲。
歡迎關(guān)注我的公眾號文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/81776.html
摘要:實現(xiàn)可伸縮的圖片墻中文指南作者簡介是推出的一個天挑戰(zhàn)。現(xiàn)在你看到的是這系列指南的第篇。完整指南在從零到壹全棧部落。實現(xiàn)效果點擊任意一張圖片,圖片展開,同時從圖片上下兩方分別移入文字。 Day05 - Flex 實現(xiàn)可伸縮的圖片墻 中文指南 作者:?liyuechun 簡介:JavaScript30 是 Wes Bos 推出的一個 30 天挑戰(zhàn)。項目免費提供了 30 個視頻教程、30 ...
摘要:關(guān)于點擊進入項目是我于開始的一個項目,每個工作日發(fā)布一道面試題。即使這個時間周期內(nèi),小明取得多次滿分。創(chuàng)建作用域鏈在執(zhí)行期上下文的創(chuàng)建階段,作用域鏈是在變量對象之后創(chuàng)建的。這種一層一層的關(guān)系,就是作用域鏈。 關(guān)于【Step-By-Step】 Step-By-Step (點擊進入項目) 是我于 2019-05-20 開始的一個項目,每個工作日發(fā)布一道面試題。每個周末我會仔細閱讀大家的答...
摘要:關(guān)于點擊進入項目是我于開始的一個項目,每個工作日發(fā)布一道面試題。即使這個時間周期內(nèi),小明取得多次滿分。創(chuàng)建作用域鏈在執(zhí)行期上下文的創(chuàng)建階段,作用域鏈是在變量對象之后創(chuàng)建的。這種一層一層的關(guān)系,就是作用域鏈。 關(guān)于【Step-By-Step】 Step-By-Step (點擊進入項目) 是我于 2019-05-20 開始的一個項目,每個工作日發(fā)布一道面試題。每個周末我會仔細閱讀大家的答...
摘要:介一回聊狀態(tài)模式,官方描述允許一個對象在其內(nèi)部狀態(tài)改變時改變它的行為。有限狀態(tài)機有限狀態(tài)機是一個非常有用的模型,可以模擬世界上大部分事物。這個是官方說法,簡單說,她有三個特征,狀態(tài)總數(shù)是有限的。,任一時刻,只處在一種狀態(tài)之中。 本回內(nèi)容介紹 上一回聊了聊組合模式(Composite),用組合模式模擬了個圖片庫,聊了遞歸。介一回聊狀態(tài)模式(State),官方描述允許一個對象在其內(nèi)部狀態(tài)改...
閱讀 2666·2023-04-25 15:22
閱讀 2837·2021-10-11 10:58
閱讀 1059·2021-08-30 09:48
閱讀 1864·2019-08-30 15:56
閱讀 1740·2019-08-30 15:53
閱讀 1106·2019-08-29 11:16
閱讀 1058·2019-08-23 18:34
閱讀 1649·2019-08-23 18:12
极致性价比!云服务器续费无忧!
Tesla A100/A800、Tesla V100S等多种GPU云主机特惠2折起,不限台数,续费同价。
NVIDIA RTX 40系,高性价比推理显卡,满足AI应用场景需要。
乌兰察布+上海青浦,满足东推西训AI场景需要