摘要:執(zhí)行上下文棧通過上文我們知道預處理全局代碼時,會產(chǎn)生一個執(zhí)行上下文環(huán)境。實現(xiàn)這一壓棧出棧過程的機制就是執(zhí)行上下文棧。
JavaScript的解析(預處理)與執(zhí)行
詳見:http://www.cnblogs.com/foodoi...
執(zhí)行上下文JavaScript在執(zhí)行一個“代碼段”之前,即解析(預處理)階段,會先進行一些“準備工作”,例如掃描JS中var定義的變量、函數(shù)名等,進而生成執(zhí)行上下文。
JS中的“代碼段”分為三種:全局代碼段、函數(shù)體代碼段、eval代碼段。(注:ES6之前,JS不存在“代碼塊”作用域的概念,即除了函數(shù)之外所有“{}”里的代碼,都屬于全局作用域)
全局代碼段“準備工作”包括:
1.變量、函數(shù)表達式 —— 變量聲明,默認賦值為undefined; 2.this —— 賦值; 3.函數(shù)聲明 —— 賦值。
函數(shù)體代碼段“準備工作”包括:
1.變量、函數(shù)表達式 —— 變量聲明,默認賦值為undefined; 2.this —— 賦值; 3.函數(shù)聲明 —— 賦值; 4.參數(shù) —— 賦值; 5.argument —— 賦值; 6.自由變量的取值作用域 —— 賦值。
evel()不推薦使用,所以不再分析evel代碼段。
至此,“執(zhí)行上下文”的定義可以通俗化為 —— 在執(zhí)行代碼段之前(預處理階段),把將要用到的所有變量都事先拿出來,有的直接賦值,有的先用undefined占個空,這些變量共同組成的詞法環(huán)境,即為執(zhí)行上下文環(huán)境。
在執(zhí)行js代碼時,會有數(shù)不清的函數(shù)調(diào)用次數(shù),會產(chǎn)生許多個上下文環(huán)境。這么多上下文環(huán)境該如何管理,以及如何銷毀并釋放內(nèi)存呢?這就需要“執(zhí)行上下文棧”來解釋了。
執(zhí)行上下文棧通過上文我們知道:預處理全局代碼時,會產(chǎn)生一個執(zhí)行上下文環(huán)境。每次調(diào)用函數(shù)的預處理時,都會產(chǎn)生一個執(zhí)行上下文環(huán)境。其實,當這個函數(shù)調(diào)用完成時,它的執(zhí)行上下文環(huán)境以及其中的數(shù)據(jù)就會被銷毀,執(zhí)行過程再重新回到全局上下文環(huán)境。同一時刻,處于活動狀態(tài)的執(zhí)行上下文環(huán)境只有一個。
實現(xiàn)這一壓棧出棧過程的機制就是“執(zhí)行上下文棧”。
執(zhí)行上下文棧的壓棧出棧過程實例代碼:
var a = 10, //1.進入全局上下文環(huán)境 fn, bar = function(x) { var b = 5; fn(x+b); //3.進入fn函數(shù)上下文環(huán)境 }; fn = function(y) { var c = 5; console.log(y+c); } bar(10); //2.進入bar函數(shù)上下文環(huán)境
預處理時,首先創(chuàng)建全局上下文環(huán)境:
然后執(zhí)行代碼,全局上下文環(huán)境中的變量都被賦值:
當執(zhí)行到調(diào)用bar函數(shù)時,跳轉(zhuǎn)到bar函數(shù)內(nèi)部,對其進行預處理,創(chuàng)建bar函數(shù)的執(zhí)行上下文環(huán)境:
并將這個函數(shù)上下文環(huán)境壓棧,設(shè)置為活動狀態(tài),開始執(zhí)行bar函數(shù)體內(nèi)代碼:
當執(zhí)行到調(diào)用fn函數(shù)時,跳轉(zhuǎn)到bar函數(shù)內(nèi)部,對其進行預處理,創(chuàng)建fn函數(shù)的執(zhí)行上下文環(huán)境,并壓棧,設(shè)置為活動狀態(tài),開始執(zhí)行fn函數(shù)體內(nèi)代碼:
fn函數(shù)執(zhí)行完畢后,此次調(diào)用fn所生成的上下文環(huán)境出棧,并且被銷毀(已經(jīng)用完了,就要及時銷毀,釋放內(nèi)存),bar函數(shù)的執(zhí)行上下文環(huán)境回到活動狀態(tài):
bar函數(shù)執(zhí)行完畢后,調(diào)用bar函數(shù)所生成的上下文環(huán)境出棧,并且被銷毀(已經(jīng)用完了,就要及時銷毀,釋放內(nèi)存),全局上下文環(huán)境回到活動狀態(tài):
全局代碼執(zhí)行完成,全局上下文環(huán)境出棧,并且銷毀(已經(jīng)用完了,就要及時銷毀,釋放內(nèi)存),代碼執(zhí)行完畢。
以上是一段代碼執(zhí)行上下文環(huán)境的完整變化過程,但有一種情況的代碼,其執(zhí)行上下文環(huán)境并未按上述過程銷毀,這就是接下來我們的重點研究對象 —— 閉包!
要談閉包,我們還得先認識下作用域和自由變量,敬請期待... ...
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/91710.html
摘要:執(zhí)行上下文和執(zhí)行棧是中關(guān)鍵概念之一,是難點之一。理解執(zhí)行上下文和執(zhí)行棧同樣有助于理解其他的概念如提升機制作用域和閉包等。函數(shù)執(zhí)行完成,函數(shù)的執(zhí)行上下文出棧,并且被銷毀。 前言 如果你是一名 JavaScript 開發(fā)者,或者想要成為一名 JavaScript 開發(fā)者,那么你必須知道 JavaScript 程序內(nèi)部的執(zhí)行機制。執(zhí)行上下文和執(zhí)行棧是JavaScript中關(guān)鍵概念之一,是Ja...
摘要:執(zhí)行上下文和執(zhí)行棧是中關(guān)鍵概念之一,是難點之一。理解執(zhí)行上下文和執(zhí)行棧同樣有助于理解其他的概念如提升機制作用域和閉包等。函數(shù)執(zhí)行完成,函數(shù)的執(zhí)行上下文出棧,并且被銷毀。 前言 如果你是一名 JavaScript 開發(fā)者,或者想要成為一名 JavaScript 開發(fā)者,那么你必須知道 JavaScript 程序內(nèi)部的執(zhí)行機制。執(zhí)行上下文和執(zhí)行棧是JavaScript中關(guān)鍵概念之一,是Ja...
摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。 (關(guān)注福利,關(guān)注本公眾號回復[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,今天是第二天。 本計劃一共28期,每期...
摘要:以上是從作用域的角度對閉包的理解,我們還可以結(jié)合執(zhí)行上下文棧來理解閉包。這就是需要理解閉包的核心內(nèi)容。即,執(zhí)行到第行時,全局上下文環(huán)境將變?yōu)榛顒訝顟B(tài),但是上下文環(huán)境依然會在執(zhí)行上下文棧中。 理解了上下文環(huán)境、作用域、作用域鏈以及自由變量,我們再來聊聊閉包。 我們不急于給出閉包的概念,先從應用閉包的兩種情況 —— 1.函數(shù)作為返回值,2.函數(shù)作為參數(shù)被傳遞 —— 來直觀的認識它。 第一,...
摘要:首次運行代碼時,會創(chuàng)建一個全局執(zhí)行上下文并到當前的執(zhí)行棧中。執(zhí)行上下文的創(chuàng)建執(zhí)行上下文分兩個階段創(chuàng)建創(chuàng)建階段執(zhí)行階段創(chuàng)建階段確定的值,也被稱為。 (關(guān)注福利,關(guān)注本公眾號回復[資料]領(lǐng)取優(yōu)質(zhì)前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調(diào)用堆棧,,今天是第一天 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進...
閱讀 2757·2023-04-25 14:15
閱讀 2704·2021-11-04 16:11
閱讀 3395·2021-10-14 09:42
閱讀 442·2019-08-30 15:52
閱讀 2826·2019-08-30 14:03
閱讀 3546·2019-08-30 13:00
閱讀 2112·2019-08-26 11:40
閱讀 3308·2019-08-26 10:25