原文地址:Understanding Execution Context and Execution Stack in Javascript
原文作者:Sukhjinder Arora
译文出自:掘金翻译计划
本文永久链接:github.com/xitu/gold-m…
译者:CoolRice
校对者:, CoderMing
此文參考自:子非
連結:https://juejin.im/post/6844903682283143181
來源:掘金
使用 Bit 应用所提供的组件作为构建模块,你就是架构师。随时随地和你的团队分享、发现和开发组件,快来尝试鲜!
執行JavaScript的環境
每當執行JavaScript代碼都是在執行上下文裡面執行
全局執行上下文(一個程序只會有一個)
最基礎的上下文,只要不是在函數裡面的代碼都是存在於全局執行上下文
作用:
函數執行上下文 (每當函數被調用就會產生一個執行上下文)
後續會解釋,先有個印象就好
eval 執行上下文
eval 函數內部執行的代碼也會有自己的上下文(但因為不常用,所以先跳過吧~~~)
首先先給大家科普棧結構是甚麼
一種數據結構,按照後進先出模式(LIFO)儲存資料
比方說下面這張圖,要變成左圖這樣要先依序裝進A、B、C,今天想要更改數據(比方說希望變成右圖)
經過步驟:
拿出C => 拿出B => 拿出A => 放進C => 放進B => 放進A
有發現嗎,後裝進去的會先被取出來(構成左圖的順序是放A放B放C,但先拿出來的一定是C)
即是其他語言的調用棧,用來儲存代碼執行時候的所有執行上下文
直接來例子
例子:
function foo() {
console.log('bar');
bar()
}
function bar() {
console.log('bar');
}
foo()
console.log('結束');
運行邏輯:
- 一開始執行JS代碼,JS引擎會立即創建全局上下文並將它壓進執行棧裡面(就是放進去)
- 然後執行了foo函數(非聲明!),創建 foo 上下文壓進棧裡面
- 接著foo函數內部運行了bar函數,創建bar上下文壓進棧裡
- 當bar函數執行完成就出棧
- foo函數執行完成出棧
- 所有代碼完成全局出棧
創建分成兩個步驟
- 創建階段
- 執行階段
總共發生三件事
- this指向的決定
- 創建詞法環境
- 創建變量環境
可參考其他文章,會有更詳細的說明
懶人包:
持有 標識符—變量映射 的結構
標識符: 比方說變量或是函數的名子
變量: 數據引用
環境紀錄器:
儲存變量和函數聲明的位子
外部環境的引用:
可以訪問父層的詞法環境 (作用域)
全局環境(全局執行上下文裡面):
外部環境引用指向null,在環境記錄器( 對象環境記錄器 )內的原型函數(window對象)還有任何用戶定義的全局變量
函數環境:
函數內部用戶定義的變量存儲在環境記錄器( 聲明式環境記錄器 )中。並且引用的外部環境可能是全局環境,或者任何包含此內部函數的外部函數。
詞法環境的內部有兩個組件:
環境紀錄器
存儲變量和函數聲明的實際位置。
同樣是一個詞法環境(有著上面定義的詞法環境的所有屬性),其環境記錄器持有變量聲明語句在執行上下文中創建的綁定關係。
在ES6中,詞法環境組件和變量環境的一個不同就是前者被用來存儲函數聲明和變量(
let
和const
)綁定,而後者只用來存儲var
變量綁定。
分配好變量,就可以執行了
Bit 使得在项目和应用中分享小型组件和模块变得非常简单,使您和您的团队可以更快地构建代码。随时随地和你的团队分享、发现和开发组件,快来尝鲜!
如果发现译文存在错误或其他需要改进的地方,欢迎到 掘金翻译计划 对译文进行修改并 PR,也可获得相应奖励积分。文章开头的 本文永久链接 即为本文在 GitHub 上的 MarkDown 链接。