【進階1-1期】理解JavaScript 中的執行上下文和執行棧

(關注福利,關注本公衆號回覆[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導)前端

本週正式開始前端進階的第一期,本週的主題是調用堆棧,,今天是第一天node

本計劃一共28期,每期重點攻克一個面試重難點,若是你還不瞭解本進階計劃,點擊查看前端進階的破冰之旅webpack

本期推薦文章

理解JavaScript 中的執行上下文和執行棧,因爲微信不能訪問外鏈,點擊閱讀原文就能夠啦。git

推薦理由

首先這是一篇譯文,文章翻譯的挺好,詳細介紹了執行上下文的類型和建立過程,對於理解JS運行機制有極大的幫助,特別是從另外一個角度介紹了ES5/6狀況下變量提高的狀況和緣由。github

閱讀筆記

執行上下文是當前 JavaScript 代碼被解析和執行時所在環境的抽象概念。web

執行上下文的類型

執行上下文總共有三種類型面試

  • 全局執行上下文:只有一個,瀏覽器中的全局對象就是 window 對象,this 指向這個全局對象。
  • 函數執行上下文:存在無數個,只有在函數被調用的時候纔會被建立,每次調用函數都會建立一個新的執行上下文。
  • Eval 函數執行上下文: 指的是運行在 eval 函數中的代碼,不多用並且不建議使用。

執行棧

執行棧,也叫調用棧,具備 LIFO(後進先出)結構,用於存儲在代碼執行期間建立的全部執行上下文。算法

首次運行JS代碼時,會建立一個全局執行上下文並Push到當前的執行棧中。每當發生函數調用,引擎都會爲該函數建立一個新的函數執行上下文並Push到當前執行棧的棧頂。跨域

根據執行棧LIFO規則,當棧頂函數運行完成後,其對應的函數執行上下文將會從執行棧中Pop出,上下文控制權將移到當前執行棧的下一個執行上下文。數組

執行上下文的建立

執行上下文分兩個階段建立:1)建立階段; 2)執行階段

建立階段

  • 一、肯定 this 的值,也被稱爲 This Binding
  • 二、LexicalEnvironment(詞法環境) 組件被建立。
  • 三、VariableEnvironment(變量環境) 組件被建立。

直接看僞代碼可能更加直觀

ExecutionContext = {  
  ThisBinding = <this value>,     // 肯定this 
  LexicalEnvironment = { ... },   // 詞法環境
  VariableEnvironment = { ... },  // 變量環境
}
This Binding
  • 全局執行上下文中,this 的值指向全局對象,在瀏覽器中this 的值指向 window 對象,而在nodejs中指向這個文件的module對象。
  • 函數執行上下文中,this 的值取決於函數的調用方式。具體有:默認綁定、隱式綁定、顯式綁定(硬綁定)、new綁定、箭頭函數,具體內容會在【this全面解析】部分詳解。
詞法環境(Lexical Environment)

詞法環境有兩個組成部分

  • 一、環境記錄:存儲變量和函數聲明的實際位置
  • 二、對外部環境的引用:能夠訪問其外部詞法環境

詞法環境有兩種類型

  • 一、全局環境:是一個沒有外部環境的詞法環境,其外部環境引用爲 null。擁有一個全局對象(window 對象)及其關聯的方法和屬性(例如數組方法)以及任何用戶自定義的全局變量,this 的值指向這個全局對象。
  • 二、函數環境:用戶在函數中定義的變量被存儲在環境記錄中,包含了arguments 對象。對外部環境的引用能夠是全局環境,也能夠是包含內部函數的外部函數環境。

直接看僞代碼可能更加直觀

GlobalExectionContext = {  // 全局執行上下文
  LexicalEnvironment: {          // 詞法環境
    EnvironmentRecord: {           // 環境記錄
      Type: "Object",                 // 全局環境
      // 標識符綁定在這裏 
      outer: <null>                    // 對外部環境的引用
  }  
}

FunctionExectionContext = { // 函數執行上下文
  LexicalEnvironment: {        // 詞法環境
    EnvironmentRecord: {          // 環境記錄
      Type: "Declarative",         // 函數環境
      // 標識符綁定在這裏               // 對外部環境的引用
      outer: <Global or outer function environment reference>  
  }  
}
變量環境

變量環境也是一個詞法環境,所以它具備上面定義的詞法環境的全部屬性。

在 ES6 中,詞法 環境和 變量 環境的區別在於前者用於存儲函數聲明和變量( letconst綁定,然後者僅用於存儲變量( 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 的狀況下)或保持未初始化(在 letconst 的狀況下)。因此這就是爲何能夠在聲明以前訪問 var 定義的變量(儘管是 undefined ),但若是在聲明以前訪問 letconst 定義的變量就會提示引用錯誤的緣由。這就是所謂的變量提高。

執行階段

此階段,完成對全部變量的分配,最後執行代碼。

若是 Javascript 引擎在源代碼中聲明的實際位置找不到 let 變量的值,那麼將爲其分配 undefined 值。

參考

理解 Javascript 執行上下文和執行棧

往期文章查看

每週計劃安排

每週面試重難點計劃以下,若有修改會通知你們。每週一期,爲期半年,準備明年跳槽的小夥伴們能夠把本公衆號置頂了。

  • 【進階1期】 調用堆棧
  • 【進階2期】 做用域閉包
  • 【進階3期】 this全面解析
  • 【進階4期】 深淺拷貝原理
  • 【進階5期】 原型Prototype
  • 【進階6期】 高階函數
  • 【進階7期】 事件機制
  • 【進階8期】 Event Loop原理
  • 【進階9期】 Promise原理
  • 【進階10期】Async/Await原理
  • 【進階11期】防抖/節流原理
  • 【進階12期】模塊化詳解
  • 【進階13期】ES6重難點
  • 【進階14期】計算機網絡概述
  • 【進階15期】瀏覽器渲染原理
  • 【進階16期】webpack配置
  • 【進階17期】webpack原理
  • 【進階18期】前端監控
  • 【進階19期】跨域和安全
  • 【進階20期】性能優化
  • 【進階21期】VirtualDom原理
  • 【進階22期】Diff算法
  • 【進階23期】MVVM雙向綁定
  • 【進階24期】Vuex原理
  • 【進階25期】Redux原理
  • 【進階26期】路由原理
  • 【進階27期】VueRouter源碼解析
  • 【進階28期】ReactRouter源碼解析

交流

本人Github連接以下,歡迎各位Star

http://github.com/yygmind/blog

我是木易楊,網易高級前端工程師,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!

若是你想加羣討論每期面試知識點,公衆號回覆[加羣]便可

相關文章
相關標籤/搜索