JavaScript中的執行上下文
本文主要會講解我們常看到的上下文知識點,旨在幫助自己和大家加深對它理解。本篇文章可以避開了變數提升相關知識,是希望篇幅可以控制在一定範圍,方便大家瀏覽,劇透一下《變數物件》會在下一篇和大家見面~
持續更新,您的三連就是我最大的動力,虛心接受大佬們的批評與指點,共勉!
目錄
#相關免費學習推薦:javascript影片教學
#前言
又到了修練JavaScript內功的時候了,繼上一篇《從作用域到作用域鏈》之後,我們來談一談執行上下文,在寫這篇文章的時候總感覺無法完整的將知識點串聯起來,所以希望大家也能提些建議哦,讓這篇文章更值得收藏、按讚哦~
一、怎麼描述執行上下文
1.1 本節知識導圖:
1.2 如果描述執行上下文
上述三條描述都符合執行上下文的一些特點,但重點都不一樣。
1.3 執行上下文的型別
#全域執行上下文:只有一個,瀏覽器中的全域物件就是window 對象,this 指向這個全域對象。
函數執行上下文:存在無數個,只有在函數被呼叫的時候才會被創建,每次呼叫函數都會創建一個新的執行上下文。
Eval
函數執行上下文: 指的是運行在 eval 函數中的程式碼,很少用而且不建議使用。
二、執行堆疊(Execution context stack)
大家都明白,函數的執行順序和它的定義順序沒關係,但如何解釋,就需要從執行堆疊說起了。
2.1 本節知識導圖
#2.2 描述執行堆疊
執行堆疊,也叫呼叫棧,具有LIFO(後進先出)結構,用於儲存在程式碼執行期間建立的所有執行上下文。
首次執行JS程式碼時,會建立一個全域執行上下文並Push到目前的執行上下文堆疊中。每當發生函數調用,引擎都會為該函數建立一個新的函數執行上下文並push
到目前執行堆疊的堆疊頂部。
當堆疊頂函數運行完成後,其對應的函數執行上下文將會從執行堆疊中pop
出,上下文控制權將移到目前執行堆疊的下一個執行上下文。
接下來問題來了,我們寫的函數多了去了,如何管理創建的那麼多執行上下文呢?
三、形象化執行堆疊
我們利用圖片文字描述的方式來解釋這樣幾段程式碼:
# 3.1 為了模擬執行上下文堆疊的行為,讓我們定義執行上下文堆疊為陣列:
var ECStack = [];
試想當JavaScript 開始要解釋執行程式碼的時候,最先遇到的就是全域程式碼,所以初始化的時候會先向執行上下文堆疊壓入一個全域執行上下文,我們用globalContext
表示它,而且只有當整個應用程式結束的時候,ECStack 才會被清空,所以程式結束之前, ECStack 最底部永遠有個globalContext
:
ECStack.push('globalContext');ECStack // ["globalContext"]
現在JavaScript 遇到下面的這段程式碼了:
function fun1() { fun2();}function fun2() { fun3();}function fun3() { console.log('最后打印3')}fun1(); // 最后打印3
當執行一個函數的時候,就會建立一個執行上下文,並且壓入(push
)執行上下文棧,當函數執行完畢的時候,就會將函數的執行上下文從堆疊中彈出(pop
)。知道了這樣的工作原理,讓我們來看看如何處理上面這段程式碼:
// 伪代码// fun1()ECStack.push(<fun1> functionContext);// fun1中竟然调用了fun2,还要创建fun2的执行上下文ECStack.push(<fun2> functionContext);// 擦,fun2还调用了fun3!ECStack.push(<fun3> functionContext);// fun3执行完毕ECStack.pop();// fun2执行完毕ECStack.pop();// fun1执行完毕ECStack.pop();// javascript接着执行下面的代码,但是ECStack底层永远有个globalContext</fun3></fun2></fun1>
#再看如下代碼:
console.log(1);function father() { console.log(2); (function child() { console.log(3); }()); console.log(4);}father();console.log(5);//会依次输出 1 2 3 4 5
分析它的執行堆疊經歷了什麼:
其實到這裡我們已經大致了解了執行堆疊在函數執行前->執行後的流程了,但下一篇文章我們會詳細了解釋一下,感興趣的小伙伴不妨點個關注,不跑丟哦~
四、思考題
#現在我們已經了解了執行上下文堆疊是如何處理執行上下文的,所以讓我們看看上篇文章《從作用域到作用域鏈》最後的問題:
var scope = "global scope";function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f();}checkscope();
var scope = "global scope";function checkscope(){ var scope = "local scope"; function f(){ return scope; } return f;}checkscope()();
兩段程式碼執行的結果一樣,但是兩段程式碼究竟有哪些不同呢?
答案就是執行上下文堆疊的變化不一樣。
讓我們模擬第一段程式碼:
ECStack.push(<checkscope> functionContext);ECStack.push(<f> functionContext);ECStack.pop();ECStack.pop();</f></checkscope>
讓我們模擬第二段程式碼:
ECStack.push(<checkscope> functionContext);ECStack.pop();ECStack.push(<f> functionContext);ECStack.pop();</f></checkscope>
如果像上一小結一樣畫個圖的話,兩段程式碼確實很不同哦~
相關免費學習推薦:javascript##(影片)
#
以上是JavaScript如何執行上下文的詳細內容。更多資訊請關注PHP中文網其他相關文章!