(關注福利,關注本公衆號回覆[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導)前端
本週正式開始前端進階的第一期,本週的主題是調用堆棧,,今天是第一天node
本計劃一共28期,每期重點攻克一個面試重難點,若是你還不瞭解本進階計劃,點擊查看前端進階的破冰之旅webpack
理解JavaScript 中的執行上下文和執行棧,因爲微信不能訪問外鏈,點擊閱讀原文就能夠啦。git
首先這是一篇譯文,文章翻譯的挺好,詳細介紹了執行上下文的類型和建立過程,對於理解JS運行機制有極大的幫助,特別是從另外一個角度介紹了ES5/6狀況下變量提高的狀況和緣由。github
執行上下文是當前 JavaScript 代碼被解析和執行時所在環境的抽象概念。web
執行上下文總共有三種類型面試
this
指向這個全局對象。eval
函數中的代碼,不多用並且不建議使用。執行棧,也叫調用棧,具備 LIFO(後進先出)結構,用於存儲在代碼執行期間建立的全部執行上下文。算法
首次運行JS代碼時,會建立一個全局執行上下文並Push到當前的執行棧中。每當發生函數調用,引擎都會爲該函數建立一個新的函數執行上下文並Push到當前執行棧的棧頂。跨域
根據執行棧LIFO規則,當棧頂函數運行完成後,其對應的函數執行上下文將會從執行棧中Pop出,上下文控制權將移到當前執行棧的下一個執行上下文。數組
執行上下文分兩個階段建立:1)建立階段; 2)執行階段
直接看僞代碼可能更加直觀
ExecutionContext = { ThisBinding = <this value>, // 肯定this LexicalEnvironment = { ... }, // 詞法環境 VariableEnvironment = { ... }, // 變量環境 }
this
的值指向全局對象,在瀏覽器中this
的值指向 window
對象,而在nodejs
中指向這個文件的module
對象。this
的值取決於函數的調用方式。具體有:默認綁定、隱式綁定、顯式綁定(硬綁定)、new
綁定、箭頭函數,具體內容會在【this全面解析】部分詳解。詞法環境有兩個組成部分
詞法環境有兩種類型
this
的值指向這個全局對象。arguments
對象。對外部環境的引用能夠是全局環境,也能夠是包含內部函數的外部函數環境。直接看僞代碼可能更加直觀
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> } }
變量提高的緣由:在建立階段,函數聲明存儲在環境中,而變量會被設置爲 undefined
(在 var
的狀況下)或保持未初始化(在 let
和 const
的狀況下)。因此這就是爲何能夠在聲明以前訪問 var
定義的變量(儘管是 undefined
),但若是在聲明以前訪問 let
和 const
定義的變量就會提示引用錯誤的緣由。這就是所謂的變量提高。
此階段,完成對全部變量的分配,最後執行代碼。
若是 Javascript 引擎在源代碼中聲明的實際位置找不到 let
變量的值,那麼將爲其分配 undefined
值。
理解 Javascript 執行上下文和執行棧
每週面試重難點計劃以下,若有修改會通知你們。每週一期,爲期半年,準備明年跳槽的小夥伴們能夠把本公衆號置頂了。
本人Github連接以下,歡迎各位Star
http://github.com/yygmind/blog
我是木易楊,網易高級前端工程師,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!
若是你想加羣討論每期面試知識點,公衆號回覆[加羣]便可