摘要:什么是中的調(diào)用棧調(diào)用棧就像是程序當(dāng)前執(zhí)行的日志。當(dāng)函數(shù)執(zhí)行結(jié)束時,將從調(diào)用棧中出去。了解全局和局部執(zhí)行上下文是掌握作用域和閉包的關(guān)鍵。總結(jié)引擎創(chuàng)建執(zhí)行上下文,全局存儲器和調(diào)用棧。
原文作者:Valentino 原文鏈接:https://www.valentinog.com/blog/js-execution-context-call-stack什么是Javascript中的執(zhí)行上下文?
我打賭你不知道答案。
編程語言中最基礎(chǔ)的組成部分是什么?
變量和函數(shù)對嗎?每個人都可以學(xué)習(xí)這些板塊。
但除了基礎(chǔ)知識之外還有什么?
在稱自己為中級(甚至是高級)Javascript開發(fā)人員之前,你應(yīng)該掌握的Javascript的核心是什么?
有很多:Scope(作用域)、Closure(閉包)、Callbacks(回調(diào))、Prototype(原型)等等。
但在深入研究這些概念之前,您至少應(yīng)該了解Javascript引擎的工作原理。
在這篇文章中,我們將介紹每個Javascript引擎的兩個基本部分:執(zhí)行上下文和調(diào)用堆棧。
(不要害怕。它比你想象的容易)。
準(zhǔn)備好了嗎?
目錄
你會學(xué)到什么?
Javascript如何執(zhí)行您的代碼?
Javascript引擎
它是如何工作的?
全局存儲器?
什么是調(diào)用棧?
什么是局部執(zhí)行上下文?
總結(jié)
你會學(xué)到什么?在這篇文章中你將學(xué)到:
Javascript引擎是如何工作的?
Javascript中執(zhí)行上下文
什么是調(diào)用棧
全局執(zhí)行上下文和局部執(zhí)行上下文之間的區(qū)別
Javascript如何執(zhí)行您的代碼?通過查看Javascript內(nèi)部功能,您將成為更好的Javascript開發(fā)人員,即使您無法掌握每一個細(xì)節(jié)。
現(xiàn)在,看看下面的代碼:
var num = 2; function pow(num) { return num * num; }
現(xiàn)在告訴我:你認(rèn)為在瀏覽器里以何種順序執(zhí)行這段代碼?
換句話說,如果您是瀏覽器,您將如何閱讀該代碼?
這聽起來很簡單。
大多數(shù)人認(rèn)為“是的,瀏覽器執(zhí)行功能pow并返回結(jié)果,然后將2分配給num。”
在接下來的部分中,您將發(fā)現(xiàn)那些看似簡單的代碼行背后的機制。
Javascript引擎要了解Javascript如何運行您的代碼,我們應(yīng)該遇到第一件可怕的事情:
執(zhí)行上下文
在Javascript中什么是執(zhí)行上下文?
每次在瀏覽器(或Node)中運行Javascript時,引擎都會執(zhí)行一系列步驟。
其中一個步驟涉及創(chuàng)建全局執(zhí)行上下文。
什么是引擎?
也就是說,Javascript引擎是運行Javascript代碼的“引擎”。
如今有兩個突出的Javascript引擎:Google V8和SpiderMonkey。
V8是Google開源的Javascript引擎,在Google Chrome和Nodejs中使用。
SpiderMonkey是Mozilla的JavaScript引擎,用于Firefox。
到目前為止,我們有Javascript引擎和執(zhí)行上下文。
現(xiàn)在是時候了解它們?nèi)绾螀f(xié)同工作了。
它是如何工作的?每次運行一些Javascript代碼是,引擎都會創(chuàng)造一個全局執(zhí)行上下文。
執(zhí)行上下文是一個比喻的詞,用于描述運行Javascript代碼的環(huán)境。
我覺得你很難想象出這些抽象的東西。
現(xiàn)在將全局執(zhí)行上下文視為一個框:
讓我們再看看我們的代碼:
var num = 2; function pow(num) { return num * num; }
引擎如何讀取該代碼?
這是一個簡化版本:
引擎:第一行,它是變量!讓我們將它存儲在全局存儲器中。
引擎:第三行,我看到了一個函數(shù)聲明。讓我們也把它存儲在全局存儲器中。
引擎:看起來我已經(jīng)完成了。
如果我再次問你:瀏覽器如何“看到”以下代碼,你會怎么說?
是的,它有點自上而下......
正如你所看到的那樣,引擎沒有運行功能pow!
這是一個函數(shù)聲明,而不是函數(shù)調(diào)用。
上面的代碼將轉(zhuǎn)換為存儲在全局存儲器中的一些值:函數(shù)聲明和變量。
全局存儲器?
我已經(jīng)對執(zhí)行上下文感到困惑,現(xiàn)在還要問我什么是全局存儲器?
接下來讓我們看看什么是全局存儲器
全局存儲器Javascript引擎也有一個全局存儲器。
全局內(nèi)存包含全局變量和函數(shù)聲明供以后使用。
如果您閱讀Kyle Simpson的“作用域和閉包”,您可能會發(fā)現(xiàn)全局存儲器與全局作用域的概念重疊。
實際上它們是一回事。
這是些很難得概念。
但你現(xiàn)在不應(yīng)該擔(dān)心。
我希望你能理解我們難題的兩個重要部分。
當(dāng)Javascript引擎運行您的代碼時,它會創(chuàng)建:
全局執(zhí)行上下文
全局存儲器(也稱為全局作用域或全局變量環(huán)境)
一切都清楚了嗎?
如果我在這一點上,我會:
寫下一些Javascript代碼
當(dāng)你是引擎時,一步一步地解析代碼
在執(zhí)行期間創(chuàng)建全局執(zhí)行上下文和全局存儲器的圖形表示
您可以在紙上或使用原型制作工具編寫練習(xí)。
對于我的小例子,圖片看起來如下:
在下一節(jié)中,我們將看另一個可怕的事情:調(diào)用棧。
什么是調(diào)用棧?您是否清楚地了解了執(zhí)行上下文,全局存儲器和Javascript引擎如何組合在一起?
如果沒有,花時間查看上一節(jié)。
我們將在我們的難題中介紹另一篇文章:調(diào)用棧。
讓我們首先回顧一下Javascript引擎運行代碼時會發(fā)生什么。 它創(chuàng)建:
全局執(zhí)行上下文
全局存儲器
除了我們的例子,沒有更多的事情發(fā)生:
var num = 2; function pow(num) { return num * num; }
代碼是純粹的值分配。
讓我們更進(jìn)一步。
如果我調(diào)用該函數(shù)會發(fā)生什么?
var num = 2; function pow(num) { return num * num; } var res = pow(num)
有趣的問題。
在Javascript中調(diào)用函數(shù)的行為使引擎尋求幫助。
這個幫助來自Javascript引擎的朋友:調(diào)用棧。
它聽起來可能并不明顯,但Javascript引擎需要跟蹤發(fā)生的情況。
它依賴于調(diào)用棧。
什么是Javascript中的調(diào)用棧?
調(diào)用棧就像是程序當(dāng)前執(zhí)行的日志。
實際上它是一個數(shù)據(jù)結(jié)構(gòu):堆棧。
調(diào)用棧的工作原理是什么?
不出所料,它有兩種方法:push和pop。
push是將某些東西放入堆棧的行為。
也就是說,當(dāng)您在Javascript中運行函數(shù)時,引擎會將該函數(shù)push到調(diào)用堆棧中。
每個函數(shù)調(diào)用都被push到調(diào)用棧中。
push的第一件事是main()(或global()),它是Javascript程序執(zhí)行的主要線程。
現(xiàn)在,上一張圖片看起來像這樣:
pop另一端是從堆棧中刪除某些東西的行為。
當(dāng)函數(shù)執(zhí)行結(jié)束時,將從調(diào)用棧中pop出去。
我們的調(diào)用棧將如下所示:
現(xiàn)在?您已準(zhǔn)備好從那里掌握每個Javascript概念。
請看下一部分。
局部執(zhí)行上下文到目前為止,一切似乎都很清楚。
我們知道Javascript引擎創(chuàng)建了一個全局執(zhí)行上下文和一個全局存儲器。
然后,當(dāng)您在代碼中調(diào)用函數(shù)時:
Javascript引擎請求幫助
這個幫助來自Javascript引擎的朋友:調(diào)用棧
調(diào)用棧會跟蹤代碼中調(diào)用的函數(shù)
當(dāng)你在Javascript中運行一個函數(shù)時,還有另一件事情發(fā)生。
首先,該功能出現(xiàn)在全局執(zhí)行上下文中。
然后,另一個迷你上下文出現(xiàn)在函數(shù)旁邊:
那個迷你上下文叫做局部執(zhí)行上下文。
如果您注意到,在上一張圖片中,全局存儲器中會出現(xiàn)一個新變量:var res。
變量res的值首先是undefined。
然后,只要pow出現(xiàn)在全局執(zhí)行上下文中,該函數(shù)就會執(zhí)行并且res將獲取其返回值。
在執(zhí)行階段,創(chuàng)建局部執(zhí)行上下文以保存局部變量。
記住這一點。
了解全局和局部執(zhí)行上下文是掌握作用域和閉包的關(guān)鍵。
總結(jié)Javascript引擎創(chuàng)建執(zhí)行上下文,全局存儲器和調(diào)用棧。但是一旦你調(diào)用一個函數(shù),引擎就會創(chuàng)建一個局部執(zhí)行上下文。
經(jīng)常被忽視的是,新的開發(fā)人員總是將Javascript內(nèi)部視為神秘的東西。
然而,它們是掌握高級Javascript概念的關(guān)鍵。
如果你學(xué)習(xí)執(zhí)行上下文,全局存儲器和調(diào)用棧,那么Scope,Closures,Callbacks和其他東西將變得輕而易舉。
特別是,理解調(diào)用堆棧是至關(guān)重要的。
一旦你想象它,所有的Javascript將開始有意義:你將最終理解為什么Javascript是異步的以及我們?yōu)槭裁葱枰卣{(diào)。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/98295.html
摘要:執(zhí)行上下文可以理解為當(dāng)前代碼的執(zhí)行環(huán)境,它會形成一個作用域。棧底永遠(yuǎn)都是全局上下文,而棧頂就是當(dāng)前正在執(zhí)行的上下文。我們用來表示處理執(zhí)行上下文組的堆棧。因此第三步是的執(zhí)行上下文入棧。前端基礎(chǔ)進(jìn)階系列目錄 showImg(https://segmentfault.com/img/remote/1460000008315046);我們在JS學(xué)習(xí)初期或者面試的時候常常會遇到考核變量提升的思考...
摘要:不過其實簡書文章評論里有很多大家的問題以及解答,對于進(jìn)一步理解文中知識幫助很大的,算是有點可惜吧。不過也希望能夠?qū)φ趯W(xué)習(xí)前端的你有一些小幫助。如果在閱讀中發(fā)現(xiàn)了一些錯誤,請在評論里告訴我,我會及時更改。 前端基礎(chǔ)進(jìn)階(一):內(nèi)存空間詳細(xì)圖解 前端基礎(chǔ)進(jìn)階(二):執(zhí)行上下文詳細(xì)圖解 前端基礎(chǔ)進(jìn)階(三):變量對象詳解 前端基礎(chǔ)進(jìn)階(四):詳細(xì)圖解作用域鏈與閉包 前端基礎(chǔ)進(jìn)階(五):全方位...
摘要:使用上一篇文章的例子來說明下自由變量進(jìn)階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數(shù),也不是局部變量,所以是自由變量。 (關(guān)注福利,關(guān)注本公眾號回復(fù)[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導(dǎo)) 本周正式開始前端進(jìn)階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進(jìn)階計...
摘要:文章分享持續(xù)更新更多資源請文章轉(zhuǎn)自一前端文章基礎(chǔ)篇,,前端基礎(chǔ)進(jìn)階一內(nèi)存空間詳細(xì)圖解前端基礎(chǔ)進(jìn)階二執(zhí)行上下文詳細(xì)圖解前端基礎(chǔ)進(jìn)階三變量對象詳解前端基礎(chǔ)進(jìn)階四詳細(xì)圖解作用域鏈與閉包前端基礎(chǔ)進(jìn)階五全方位解讀前端基礎(chǔ)進(jìn)階六在開發(fā)者工具中觀察函數(shù)調(diào) 文章分享(持續(xù)更新) 更多資源請Star:https://github.com/maidishike... 文章轉(zhuǎn)自:https://gith...
摘要:一棧數(shù)據(jù)結(jié)構(gòu)與不同,中并沒有嚴(yán)格意義上區(qū)分棧內(nèi)存與堆內(nèi)存。引用數(shù)據(jù)類型的值是保存在堆內(nèi)存中的對象。不允許直接訪問堆內(nèi)存中的位置,因此我們不能直接操作對象的堆內(nèi)存空間。為了更好的搞懂變量對象與堆內(nèi)存,我們可以結(jié)合以下例子與圖解進(jìn)行理解。 showImg(https://segmentfault.com/img/remote/1460000009784102?w=1240&h=683); ...
閱讀 3076·2021-09-22 15:20
閱讀 2599·2019-08-30 15:54
閱讀 1965·2019-08-30 14:06
閱讀 3113·2019-08-30 13:05
閱讀 2456·2019-08-29 18:36
閱讀 567·2019-08-29 15:10
閱讀 522·2019-08-29 11:17
閱讀 816·2019-08-28 18:11