亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > JavaScript > 正文

深入理解JavaScript 中的執行上下文和執行棧

2019-11-19 12:38:54
字體:
來源:轉載
供稿:網友

如果你是或者想成為一名 JavaScript 開發者,你必須知道 JavaScript 程序內部是如何執行的。理解執行上下文和執行棧對于理解其他 JavaScript 概念(如變量聲明提升,作用域和閉包)至關重要。

正確理解執行上下文和執行棧的概念將使您成為更出色的 JavaScript 開發者。

閑話少說,讓我們開始吧 :)

分享自 Bit 的博客

使用 Bit 應用所提供的組件作為構建模塊,你就是架構師。隨時隨地和你的團隊分享、發現和開發組件,快來嘗試鮮!

Bit - 分享和創造代碼組件: Bit 能幫助你在不同項目和應用中分享、發現和使用代碼組件來創建新功能和……

什么是執行上下文?

簡而言之,執行上下文是評估和執行 JavaScript 代碼的環境的抽象概念。每當 Javascript 代碼在運行的時候,它都是在執行上下文中運行。

執行上下文的類型

JavaScript 中有三種執行上下文類型。

  • 全局執行上下文 ― 這是默認或者說基礎的上下文,任何不在函數內部的代碼都在全局上下文中。它會執行兩件事:創建一個全局的 window 對象(瀏覽器的情況下),并且設置 this 的值等于這個全局對象。一個程序中只會有一個全局執行上下文。
  • 函數執行上下文 ― 每當一個函數被調用時, 都會為該函數創建一個新的上下文。每個函數都有它自己的執行上下文,不過是在函數被調用時創建的。函數上下文可以有任意多個。每當一個新的執行上下文被創建,它會按定義的順序(將在后文討論)執行一系列步驟。
  • Eval 函數執行上下文 ― 執行在 eval 函數內部的代碼也會有它屬于自己的執行上下文,但由于 JavaScript 開發者并不經常使用 eval,所以在這里我不會討論它。

執行棧

執行棧,也就是在其它編程語言中所說的“調用?!保且环N擁有 LIFO(后進先出)數據結構的棧,被用來存儲代碼運行時創建的所有執行上下文。

當 JavaScript 引擎第一次遇到你的腳本時,它會創建一個全局的執行上下文并且壓入當前執行棧。每當引擎遇到一個函數調用,它會為該函數創建一個新的執行上下文并壓入棧的頂部。

引擎會執行那些執行上下文位于棧頂的函數。當該函數執行結束時,執行上下文從棧中彈出,控制流程到達當前棧中的下一個上下文。

讓我們通過下面的代碼示例來理解:

let a = 'Hello World!';function first() { console.log('Inside first function'); second(); console.log('Again inside first function');}function second() { console.log('Inside second function');}first();console.log('Inside Global Execution Context');

上述代碼的執行上下文棧。

當上述代碼在瀏覽器加載時,JavaScript 引擎創建了一個全局執行上下文并把它壓入當前執行棧。當遇到 first() 函數調用時,JavaScript 引擎為該函數創建一個新的執行上下文并把它壓入當前執行棧的頂部。

當從 first() 函數內部調用 second() 函數時,JavaScript 引擎為 second() 函數創建了一個新的執行上下文并把它壓入當前執行棧的頂部。當 second() 函數執行完畢,它的執行上下文會從當前棧彈出,并且控制流程到達下一個執行上下文,即 first() 函數的執行上下文。

當 first() 執行完畢,它的執行上下文從棧彈出,控制流程到達全局執行上下文。一旦所有代碼執行完畢,JavaScript 引擎從當前棧中移除全局執行上下文。

怎么創建執行上下文?

到現在,我們已經看過 JavaScript 怎樣管理執行上下文了,現在讓我們了解 JavaScript 引擎是怎樣創建執行上下文的。
創建執行上下文有兩個階段:1) 創建階段 和 2) 執行階段。

The Creation Phase

在 JavaScript 代碼執行前,執行上下文將經歷創建階段。在創建階段會發生三件事:

  • this 值的決定,即我們所熟知的 This 綁定。
  • 創建詞法環境組件。
  • 創建變量環境組件。

所以執行上下文在概念上表示如下:

ExecutionContext = { ThisBinding = <this value>, LexicalEnvironment = { ... }, VariableEnvironment = { ... },}

This 綁定:

在全局執行上下文中,this 的值指向全局對象。(在瀏覽器中,this引用 Window 對象)。

在函數執行上下文中,this 的值取決于該函數是如何被調用的。如果它被一個引用對象調用,那么 this 會被設置成那個對象,否則 this 的值被設置為全局對象或者 undefined(在嚴格模式下)。例如:

let foo = { baz: function() { console.log(this); }}foo.baz();  // 'this' 引用 'foo', 因為 'baz' 被       // 對象 'foo' 調用let bar = foo.baz;bar();    // 'this' 指向全局 window 對象,因為       // 沒有指定引用對象

詞法環境

官方的 ES6 文檔把詞法環境定義為

詞法環境是一種規范類型,基于 ECMAScript 代碼的詞法嵌套結構來定義標識符和具體變量和函數的關聯。一個詞法環境由環境記錄器和一個可能的引用外部詞法環境的空值組成。

簡單來說詞法環境是一種持有標識符―變量映射的結構。(這里的標識符指的是變量/函數的名字,而變量是對實際對象[包含函數類型對象]或原始數據的引用)。
現在,在詞法環境的內部有兩個組件:(1) 環境記錄器和 (2) 一個外部環境的引用。

  1. 環境記錄器是存儲變量和函數聲明的實際位置。
  2. 外部環境的引用意味著它可以訪問其父級詞法環境(作用域)。

詞法環境有兩種類型:

  • 全局環境(在全局執行上下文中)是沒有外部環境引用的詞法環境。全局環境的外部環境引用是 null。它擁有內建的 Object/Array/等、在環境記錄器內的原型函數(關聯全局對象,比如 window 對象)還有任何用戶定義的全局變量,并且 this的值指向全局對象。
  • 在函數環境中,函數內部用戶定義的變量存儲在環境記錄器中。并且引用的外部環境可能是全局環境,或者任何包含此內部函數的外部函數。

環境記錄器也有兩種類型(如上!):

  • 聲明式環境記錄器存儲變量、函數和參數。
  • 對象環境記錄器用來定義出現在全局上下文中的變量和函數的關系。

簡而言之,

在全局環境中,環境記錄器是對象環境記錄器。
在函數環境中,環境記錄器是聲明式環境記錄器。

注意 ― 對于函數環境,聲明式環境記錄器還包含了一個傳遞給函數的 arguments 對象(此對象存儲索引和參數的映射)和傳遞給函數的參數的 length。

抽象地講,詞法環境在偽代碼中看起來像這樣:

GlobalExectionContext = { LexicalEnvironment: {  EnvironmentRecord: {   Type: "Object",   // 在這里綁定標識符  }  outer: <null> }}FunctionExectionContext = { LexicalEnvironment: {  EnvironmentRecord: {   Type: "Declarative",   // 在這里綁定標識符  }  outer: <Global or outer function environment reference> }}

變量環境:

它同樣是一個詞法環境,其環境記錄器持有變量聲明語句在執行上下文中創建的綁定關系。

如上所述,變量環境也是一個詞法環境,所以它有著上面定義的詞法環境的所有屬性。

在 ES6 中,詞法環境組件和變量環境的一個不同就是前者被用來存儲函數聲明和變量(let 和 const)綁定,而后者只用來存儲 var 變量綁定。

我們看點樣例代碼來理解上面的概念:

let a = 20;const b = 30;var c;function multiply(e, f) { var g = 20; return e * f * g;}c = multiply(20, 30);

執行上下文看起來像這樣:

GlobalExectionContext = { ThisBinding: <Global Object>, LexicalEnvironment: {  EnvironmentRecord: {   Type: "Object",   // 在這里綁定標識符   a: < uninitialized >,   b: < uninitialized >,   multiply: < func >  }  outer: <null> }, VariableEnvironment: {  EnvironmentRecord: {   Type: "Object",   // 在這里綁定標識符   c: undefined,  }  outer: <null> }}FunctionExectionContext = { ThisBinding: <Global Object>, LexicalEnvironment: {  EnvironmentRecord: {   Type: "Declarative",   // 在這里綁定標識符   Arguments: {0: 20, 1: 30, length: 2},  },  outer: <GlobalLexicalEnvironment> },VariableEnvironment: {  EnvironmentRecord: {   Type: "Declarative",   // 在這里綁定標識符   g: undefined  },  outer: <GlobalLexicalEnvironment> }}

注意 ― 只有遇到調用函數 multiply 時,函數執行上下文才會被創建。

可能你已經注意到 let 和 const 定義的變量并沒有關聯任何值,但 var 定義的變量被設成了 undefined。

這是因為在創建階段時,引擎檢查代碼找出變量和函數聲明,雖然函數聲明完全存儲在環境中,但是變量最初設置為 undefined(var 情況下),或者未初始化(let 和 const 情況下)。

這就是為什么你可以在聲明之前訪問 var 定義的變量(雖然是 undefined),但是在聲明之前訪問 let 和 const 的變量會得到一個引用錯誤。

這就是我們說的變量聲明提升。

執行階段

這是整篇文章中最簡單的部分。在此階段,完成對所有這些變量的分配,最后執行代碼。

注意 ― 在執行階段,如果 JavaScript 引擎不能在源碼中聲明的實際位置找到 let 變量的值,它會被賦值為 undefined。

結論

我們已經討論過 JavaScript 程序內部是如何執行的。雖然要成為一名卓越的 JavaScript 開發者并不需要學會全部這些概念,但是如果對上面概念能有不錯的理解將有助于你更輕松,更深入地理解其他概念,如變量聲明提升,作用域和閉包。

就是這樣,如果你發現這篇文章有用,請點擊 👏 按鈕并在下面自由地評論!我很樂意和你討論 😃。

分享自Bit 的博客

Bit 使得在項目和應用中分享小型組件和模塊變得非常簡單,使您和您的團隊可以更快地構建代碼。隨時隨地和你的團隊分享、發現和開發組件,快來嘗鮮!

Bit - 分享和創造代碼組件: Bit 能幫助你在不同項目和應用中分享、發現和使用代碼組件來創建新功能和……

總結

以上所述是小編給大家介紹的JavaScript 中的執行上下文和執行棧 ,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對武林網網站的支持!

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
亚洲影视中文字幕| 这里只有精品在线观看| 日韩av有码在线| 91亚洲精华国产精华| 亚洲国产成人爱av在线播放| 欧美日韩一区二区三区在线免费观看| 中文字幕日韩欧美在线| 国产欧美久久一区二区| 欧美大片第1页| 久久天天躁狠狠躁夜夜躁2014| 国产日本欧美一区| 麻豆乱码国产一区二区三区| 国产视频久久久久| 国产欧美一区二区三区四区| 国产精品久久久久7777婷婷| 精品久久久久人成| 欧美精品做受xxx性少妇| 26uuu亚洲国产精品| 欧美激情日韩图片| 国产精品专区第二| 精品国内亚洲在观看18黄| 国产日韩在线亚洲字幕中文| 国产精品久久久久久婷婷天堂| 有码中文亚洲精品| 欧美专区在线视频| 亚洲欧洲一区二区三区久久| www.日韩欧美| 一区二区三区四区在线观看视频| 亚洲欧美另类在线观看| 久久亚洲成人精品| 欧美高清第一页| 国产精品69久久久久| 精品久久久久久久久中文字幕| 日韩小视频在线| 欧美成人精品三级在线观看| 青草成人免费视频| 欧美中文在线免费| 色综合天天综合网国产成人网| 在线日韩欧美视频| 国产精品久久久久久中文字| 欧美激情精品久久久久久大尺度| 久久国产精彩视频| 亚洲精品97久久| 亚洲一区二区三区成人在线视频精品| 精品伊人久久97| 日韩美女在线观看一区| 91免费高清视频| 精品亚洲精品福利线在观看| 久久99亚洲热视| 午夜精品一区二区三区在线| 国产精品99蜜臀久久不卡二区| 九九热r在线视频精品| 中文字幕在线亚洲| 日韩大胆人体377p| 91大神在线播放精品| 欧美猛交ⅹxxx乱大交视频| 成人观看高清在线观看免费| 俺去亚洲欧洲欧美日韩| 欧美视频第一页| 亚洲国产成人精品久久久国产成人一区| 日韩av有码在线| 欧美超级乱淫片喷水| 国产亚洲综合久久| 日韩av免费看| 久久久久久有精品国产| 亚洲精品在线91| 欧美激情久久久久| 91视频免费在线| 成人中文字幕在线观看| 91精品视频在线免费观看| 国产精品亚洲第一区| 国产不卡av在线| 国产精品久久久久aaaa九色| 亚洲男人的天堂在线| 91国在线精品国内播放| 91在线视频九色| 亚洲а∨天堂久久精品9966| 亚洲自拍偷拍区| 国产成人精品久久亚洲高清不卡| 热草久综合在线| 色偷偷偷综合中文字幕;dd| 国产视频精品xxxx| 国产精品女视频| 欧美性受xxx| 欧美日韩激情视频8区| 日韩一二三在线视频播| 欧美日韩中国免费专区在线看| 久久精品国产视频| 美女福利视频一区| 欧美高跟鞋交xxxxxhd| 中文字幕欧美在线| 久久精品久久精品亚洲人| 欧美成人黑人xx视频免费观看| 一区国产精品视频| 国产精品夜色7777狼人| 欧美日本黄视频| 亚洲精品福利资源站| 日韩av网址在线观看| 亚洲午夜未满十八勿入免费观看全集| 久久久久久久影视| 久久天天躁狠狠躁夜夜av| 欧美理论电影在线观看| 亚洲精品在线看| 亚洲高清在线观看| 欧美激情亚洲自拍| 96pao国产成视频永久免费| 亚洲精品第一国产综合精品| 成人亚洲欧美一区二区三区| 久久久久亚洲精品| 日韩欧美高清在线视频| 国产精品美女主播在线观看纯欲| 中文字幕欧美日韩va免费视频| 国产精品嫩草影院一区二区| 福利视频一区二区| 国产午夜精品视频免费不卡69堂| 欧美乱妇高清无乱码| 久久久免费精品视频| 欧美日韩免费在线观看| 欧美在线视频a| 成人精品视频在线| 亚洲自拍偷拍网址| 97热在线精品视频在线观看| 日本aⅴ大伊香蕉精品视频| 亚洲娇小xxxx欧美娇小| 亚洲第一福利视频| 国产亚洲精品久久久久久| 色青青草原桃花久久综合| 欧美性猛交xxxx免费看漫画| 97视频在线观看免费高清完整版在线观看| 国产精品精品视频| 国产精品欧美激情在线播放| 国产在线播放不卡| 国产色视频一区| 午夜精品久久久久久久久久久久久| 久久免费视频在线| 国产亚洲一区精品| 91产国在线观看动作片喷水| 亚洲国产精品大全| 欧美色videos| 亚洲国产成人av在线| 国产精品成av人在线视午夜片| 久久夜色精品国产| 精品综合久久久久久97| 色噜噜狠狠狠综合曰曰曰| 色综合久久天天综线观看| 国产亚洲欧洲高清| 国产欧美精品xxxx另类| 欧美福利在线观看| 亚洲xxxx3d| 国产精品一区二区久久国产| 久久99精品久久久久久琪琪| 日本不卡视频在线播放| 亚洲二区在线播放视频| 欧美贵妇videos办公室| 日韩视频免费大全中文字幕| 久久视频在线播放| 18一19gay欧美视频网站| 欧美日韩在线观看视频| 欧美中文字幕第一页| 国产精品久久久久久久久| 欧美性猛交xxxx黑人猛交| 欧美诱惑福利视频| 色偷偷av一区二区三区| 国产成+人+综合+亚洲欧美丁香花|