對我們前端開發者理解JS
程式內部執行機制是必要的,其中一個關鍵概念就是Js
的執行上下文和執行棧。執行上下文是JS
語言較為底層的知識,學習掌握有助於我們更深入的把握JS
這門語言的本質,也有助於理解作用域、閉包、變量提升等相關知識。
程式碼執行前,瀏覽器的Js
引擎會先建立程式碼執行的環境來處理此Js
程式碼的轉換和執行,程式碼的執行環境稱為執行上下文。
執行上下文是一個抽象概念,包含目前正在運行的程式碼以及幫助其執行的所有內容。
執行上下文主要分為三類:
Eval
執行上下文— 運行在Eval
函數中程式碼時創建的環境,Eval
由於效能問題在我們平時開發中很少用到,所有這裡我們不在討論。 接下來我們將重點放在講全域上下文和函數上下文。
2.1 全域執行上下文
當我們的JS
檔案跑起來之後,首先建立的就是全域執行上下文。
當我們的檔案裡沒有一行程式碼時,全域執行上下文中比較乾淨,只有兩個東西。
Window
,Node
在環境下是Global
)this
變數(指向的還是全域物件)這時候如果我們在檔案裡寫點東西,例如我寫如下程式碼:
var name = '小明' var age = 18 function showName(){ return { name : name, age : age } }
全域執行上下文就會立刻變成這個樣子:
上圖可以看到,我們明明給name
和age
賦值了,咋還會顯示undefined
呢?這是因為執行上下文分為兩個部分,創建階段和執行階段。
以上就是建立階段的全域上下文概況,在建立階段JS
引擎將會做以下幾件事:
window
作為全域執行上下文物件this
,this
指向window
undefined
,函數宣告放入記憶體#接下來才會進入了全域執行上下文的執行階段,也就是賦值階段,如下圖:
需要注意的是執行上下文執行階段是一行一行執行的,如下圖所示:
2.2 函數執行上下文
理解完全局執行上下文,函數執行上下文也我們只需要關注它與全局上下文之間的不同即可,兩者之間不同主要表現在以下三個方面:
window
作為全域對象,而是函數執行上下文則是建立參數對象arguments
;所建立的this
也不會指向全域對象,而是取決於函數是如何呼叫的。 我們透過下面這個範例來看函數上下文不同階段的表現:
var name = '小明' var age = 18 function showName(){ return { name : name, age : age } } // 调用该函数 showName()
當我們呼叫showName
函數時,就會進入到函數執行上下文的建立階段,函數執行上下文的場景如下:
#接著就會進入到執行階段,這個階段函數內程式碼才會一行一行執行,在這個例子中,因為沒有涉及變數的修改,因此函數上下文的內容保持不變,執行完畢後,函數上下文的生命週期就結束了。
当我们调用showName
函数时,在浏览器中运行状况:
我们看到当函数执行完后,其对应的执行上下文也随之消失了。这个消失的过程,我们叫它出栈——在JS
代码执行过程中,JS
引擎会为我们创建“执行上下文栈”。
在全局代码执行前,JS
引擎为了管理执行上下文,确保程序的执行顺序。JS
引擎会创建一个栈来管理所有的所有的执行上下文对象。
因为函数上下文可能会存在多个,我们不可能保留所有的上下文。当一个函数执行完毕,其对应的上下文必须让出之前所占用的资源。因此上下文的建立和销毁,就对应了一个” 入栈 “和” 出栈 “的操作。
当我们调用一个函数的时候,就会把它的上下文推入调用栈里,执行完毕后出栈,随后再为新的函数进行入栈操作。
我们通过一个例子来看一下这个过程:
function testA(){ console.log('执行第一个测试函数的逻辑'); testB(); console.log('再次执行第一个测试函数的逻辑'); } function testB(){ console.log('执行第二个测试函数的逻辑'); } testA()
1、执行之前,全局上下文创建:
2、testA
调用,testA
对应函数上下文创建:
3、testB
调用,testB
对应函数上下文创建:
4、testB
执行完毕,对应上下文出栈,剩下testA
和全局执行上下文:
5、testA
执行完毕,对应执行上下文出栈,此时只剩下全局上下文:
在这整个过程里,调用栈的变化示意如下:
执行上下文是什么:代码执行前,Js引擎会创建代码的执行环境,代码的执行环境称作执行上下文,包含当前正在运行的代码以及帮助其执行的所有内容。
全局执行上下文:(1)将window作为全局执行上下文对象(2)创建this,this 指向window(3)给变量和函数安排内存空间(4)变量赋值undefined,函数声明放入内存(5)放入作用域链
全局与函数执行上下文不同:(1)全局:在文件执行前创建;函数:在函数调用时创建(2)全局:只创建一次;函数:调用几次创建几次(3)将window作为全局对象;函数:创建参数对象arguments,this指向调用者
执行栈:管理所有的执行上下文对象
【相关推荐:javascript视频教程、编程基础视频】
以上是一文詳解JavaScript中執行上下文與執行堆疊(圖文結合)的詳細內容。更多資訊請關注PHP中文網其他相關文章!