首頁  >  文章  >  web前端  >  手把手教你理解JS中的執行上下文

手把手教你理解JS中的執行上下文

青灯夜游
青灯夜游轉載
2021-06-02 14:20:302788瀏覽

本篇文章一步一步帶你深入理解JavaScript中的執行上下文。有一定的參考價值,有需要的朋友可以參考一下,希望對大家有幫助。

手把手教你理解JS中的執行上下文

只有了解執行上下文,才能更能理解JavaScript 語言本身,例如變數提升,作用域,閉包等

執行上下文

執行上下文是目前程式碼的執行環境。

執行上下文主要是三種類型:

  • 全域執行上下文:全域執行環境是最外圍的一個執行環境,在瀏覽器的全域物件是window, this指向這個物件

  • 函數執行上下文:可以有無數個,函數被呼叫的時候會被建立。每次呼叫函數都會建立一個新的執行上下文。

  • eval執行上下文,很少用。

每個執行上下文,都有三個重要屬性:

  • #變數物件(variable object, VO): 每個執行環境都有一個與之關聯的變數對象,環境中定義的所有變數和函數都保存在這個物件中。雖然我們寫的程式碼無法存取這個對象,但解析器在處理資料時會在後台使用它。

在函數上下文中,使用活動物件 (activation object, AO) 來表示變數物件。活動物件和變數物件其實是一個東西,只有當進入一個執行環境時,這個執行上下文的變數物件才會被激活,此時稱為 活動物件(AO),只有活動物件上的屬性才能被存取。
  • 作用域鏈(scope chain):當程式碼在一個環境中執行時,會建立變數物件的一個作用域鏈。作用域鏈的用途,是保證對執行環境有權存取的所有變數和函數的有序存取。

  • this

執行上下文的生命週期:建立-> 執行-> 回收

##執行上下文的生命週期:建立-> 執行-> 回收

1. 建立階段:
1.1 建立變數物件:
  • 初始化函數的參數arguments
  • 函數宣告
變數宣告

舉個簡單的例子來理解變數物件

function getName(name) {
    var b = 2;
    function foo() {};
    var bar = function() {};

}
getName('lucystar')
此時的AO 大致如下
AO = {
    arguments: {
        0: 'lucystar',
        length: 1
    },
    name: 'lucystar',
    b: undefined,
    foo: reference to function foo(){},
    bar: undefined
}
上面例子中涉及到了變數提升和函數提升,之前在
從JS底層理解var、let、const
這邊文章中也介紹過
1.2 建立作用域鏈

函數的作用域在函數定義的時候就確定了。作用域鏈本身包含變數對象,當查找變數時,會先從目前上下文中的變數物件中查找,如果沒有找到,就會從父級執行上下文的變數對像中查找,一直找到全域執行上下文的變數對象
1.3 確定this的指向

這部分又分為多種情況,具體的可以查看另一篇文章

一文理解this&call&apply&bind

2. 執行階段

執行變數賦值,程式碼執行

3. 回收階段

執行上下文出棧被垃圾回收機制回收。關於記憶體回收的內容,可以查看

V8記憶體管理及垃圾回收機制

執行上下文堆疊

執行上下文堆疊是用來管理執行上下文的。在執行上下文創建好後,JavaScript引擎會將執行上下文壓入到堆疊中,通常會將這種用來管理執行上下文的堆疊稱為執行上下文棧,又稱為呼叫堆疊。

let a = 'javascript';

function foo() {
    console.log('foo');
    bar();
}
function bar() {
    console.log('bar');
}
foo();
手把手教你理解JS中的執行上下文

  • 上述程式碼在瀏覽器載入時,JavaScript 引擎建立了一個全域執行上下文並把它壓入到當前執行棧。
  • 當遇到

    foo()
  • 函數呼叫時, JavaScript 引擎建立了一個 foo 函數執行上下文並把它壓入到目前執行堆疊的頂部。
  • 當從foo() 函數內部呼叫

    bar()
  • 函數時,JavaScript 引擎建立了一個bar 函數執行上下文並把它壓入到目前執行棧的頂端。
  • 當函數bar 執行完畢,它的執行上下文會從目前堆疊中彈出,控制流程到達下一個執行上下文,即

    foo()
  • 函數的執行上下文。
  • ###當foo() 執行完成,它的執行上下文從堆疊彈出,控制流程到達全域執行上下文,一旦所有程式碼執行完成,javaScript 引擎就會從目前堆疊中移除全域執行上下文。 ###
為什麼基本資料類型儲存在堆疊中,並引用資料類型儲存在堆中? JavaScript引擎需要用堆疊來維護程式執行期間​​的上下文的狀態,如果棧空間大了的話,所有資料都存放在堆疊空間裡面,會影響到上下文切換的效率,進而影響整個程式的執行效率。

更多程式相關知識,請造訪:程式設計影片! !

以上是手把手教你理解JS中的執行上下文的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除