摘要:本計劃一共期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅本期推薦文章深入之執(zhí)行上下文棧和深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。
(關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導)
本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第二天。
本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計劃,點擊查看前端進階的破冰之旅
本期推薦文章JavaScript深入之執(zhí)行上下文棧和JavaScript深入之變量對象,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。
推薦理由本期推薦了兩篇文章,主要原因是兩篇連在一起閱讀理解會更加深一些,其中部分知識我在【進階1-1期】已經介紹過了,但是本文從另一個角度介紹了執(zhí)行上下文和變量對象,條理清晰,并配有代碼解釋,值得一讀。
閱讀筆記JS是單線程的語言,執(zhí)行順序肯定是順序執(zhí)行,但是JS 引擎并不是一行一行地分析和執(zhí)行程序,而是一段一段地分析執(zhí)行,會先進行編譯階段然后才是執(zhí)行階段。
翠花,上代碼
例子一:變量提升
foo; // undefined var foo = function () { console.log("foo1"); } foo(); // foo1,foo賦值 var foo = function () { console.log("foo2"); } foo(); // foo2,foo重新賦值
例子二:函數提升
foo(); // foo2 function foo() { console.log("foo1"); } foo(); // foo2 function foo() { console.log("foo2"); } foo(); // foo2
例子三:聲明優(yōu)先級,函數 > 變量
foo(); // foo2 var foo = function() { console.log("foo1"); } foo(); // foo1,foo重新賦值 function foo() { console.log("foo2"); } foo(); // foo1
上面三個例子中,第一個例子是變量提升,第二個例子是函數提升,第三個例子是函數聲明優(yōu)先級高于變量聲明。
需要注意的是同一作用域下存在多個同名函數聲明,后面的會替換前面的函數聲明。
執(zhí)行上下文執(zhí)行上下文總共有三種類型
全局執(zhí)行上下文:只有一個,瀏覽器中的全局對象就是 window 對象,this 指向這個全局對象。
函數執(zhí)行上下文:存在無數個,只有在函數被調用的時候才會被創(chuàng)建,每次調用函數都會創(chuàng)建一個新的執(zhí)行上下文。
Eval 函數執(zhí)行上下文: 指的是運行在 eval 函數中的代碼,很少用而且不建議使用。
這部分內容在【進階1-1期】中詳細介紹了,點擊查看【進階1-1期】理解JavaScript 中的執(zhí)行上下文和執(zhí)行棧
執(zhí)行上下文棧因為JS引擎創(chuàng)建了很多的執(zhí)行上下文,所以JS引擎創(chuàng)建了執(zhí)行上下文棧(Execution context stack,ECS)來管理執(zhí)行上下文。
當 JavaScript 初始化的時候會向執(zhí)行上下文棧壓入一個全局執(zhí)行上下文,我們用 globalContext 表示它,并且只有當整個應用程序結束的時候,執(zhí)行棧才會被清空,所以程序結束之前, 執(zhí)行棧最底部永遠有個 globalContext。
ECStack = [ // 使用數組模擬棧 globalContext ];
具體執(zhí)行過程如下圖所示,這部分內容在【進階1-1期】中詳細介紹了,點擊查看【進階1-1期】理解JavaScript 中的執(zhí)行上下文和執(zhí)行棧
找不同有如下兩段代碼,執(zhí)行的結果是一樣的,但是兩段代碼究竟有什么不同?
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()();
答案是 執(zhí)行上下文棧的變化不一樣。
第一段代碼:
ECStack.push(functionContext); ECStack.push( functionContext); ECStack.pop(); ECStack.pop();
第二段代碼:
ECStack.push(函數上下文functionContext); ECStack.pop(); ECStack.push( functionContext); ECStack.pop();
在函數上下文中,用活動對象(activation object, AO)來表示變量對象。
活動對象和變量對象的區(qū)別在于
1、變量對象(VO)是規(guī)范上或者是JS引擎上實現(xiàn)的,并不能在JS環(huán)境中直接訪問。
2、當進入到一個執(zhí)行上下文后,這個變量對象才會被激活,所以叫活動對象(AO),這時候活動對象上的各種屬性才能被訪問。
調用函數時,會為其創(chuàng)建一個Arguments對象,并自動初始化局部變量arguments,指代該Arguments對象。所有作為參數傳入的值都會成為Arguments對象的數組元素。
執(zhí)行過程執(zhí)行上下文的代碼會分成兩個階段進行處理
1、進入執(zhí)行上下文
2、代碼執(zhí)行
很明顯,這個時候還沒有執(zhí)行代碼
此時的變量對象會包括(如下順序初始化):
1、函數的所有形參 (only函數上下文):沒有實參,屬性值設為undefined。
2、函數聲明:如果變量對象已經存在相同名稱的屬性,則完全替換這個屬性。
3、變量聲明:如果變量名稱跟已經聲明的形參或函數相同,則變量聲明不會干擾已經存在的這類屬性。
上代碼就直觀了
function foo(a) { var b = 2; function c() {} var d = function() {}; b = 3; } foo(1);
對于上面的代碼,這個時候的AO是
AO = { arguments: { 0: 1, length: 1 }, a: 1, b: undefined, c: reference to function c(){}, d: undefined }
形參arguments這時候已經有賦值了,但是變量還是undefined,只是初始化的值
這個階段會順序執(zhí)行代碼,修改變量對象的值,執(zhí)行完成后AO如下
AO = { arguments: { 0: 1, length: 1 }, a: 1, b: 3, c: reference to function c(){}, d: reference to FunctionExpression "d" }
總結如下:
1、全局上下文的變量對象初始化是全局對象
2、函數上下文的變量對象初始化只包括 Arguments 對象
3、在進入執(zhí)行上下文時會給變量對象添加形參、函數聲明、變量聲明等初始的屬性值
4、在代碼執(zhí)行階段,會再次修改變量對象的屬性值
參考JavaScript深入之執(zhí)行上下文棧往期文章查看
JavaScript深入之變量對象
【進階1-1期】理解JavaScript 中的執(zhí)行上下文和執(zhí)行棧
【進階1-2期】JavaScript深入之執(zhí)行上下文棧和變量對象
【進階1-3期】JavaScript深入之內存空間詳細圖解
【進階1-4期】JavaScript深入之帶你走進內存機制制
【進階1-5期】JavaScript深入之4類常見內存泄漏及如何避免
【進階2-1期】深入淺出圖解作用域鏈和閉包
每周計劃安排每周面試重難點計劃如下,如有修改會通知大家。每周一期,為期半年,準備明年跳槽的小伙伴們可以把本公眾號置頂了。
【進階1期】 調用堆棧
【進階2期】 作用域閉包
【進階3期】 this全面解析
【進階4期】 深淺拷貝原理
【進階5期】 原型Prototype
【進階6期】 高階函數
【進階7期】 事件機制
【進階8期】 Event Loop原理
【進階9期】 Promise原理
【進階10期】Async/Await原理
【進階11期】防抖/節(jié)流原理
【進階12期】模塊化詳解
【進階13期】ES6重難點
【進階14期】計算機網絡概述
【進階15期】瀏覽器渲染原理
【進階16期】webpack配置
【進階17期】webpack原理
【進階18期】前端監(jiān)控
【進階19期】跨域和安全
【進階20期】性能優(yōu)化
【進階21期】VirtualDom原理
【進階22期】Diff算法
【進階23期】MVVM雙向綁定
【進階24期】Vuex原理
【進階25期】Redux原理
【進階26期】路由原理
【進階27期】VueRouter源碼解析
【進階28期】ReactRouter源碼解析
交流本人Github鏈接如下,歡迎各位Star
http://github.com/yygmind/blog
我是木易楊,網易高級前端工程師,跟著我每周重點攻克一個前端面試重難點。接下來讓我?guī)阕哌M高級前端的世界,在進階的路上,共勉!
如果你想加群討論每期面試知識點,公眾號回復[加群]即可
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/99540.html
摘要:進階期理解中的執(zhí)行上下文和執(zhí)行棧進階期深入之執(zhí)行上下文棧和變量對象但是今天補充一個知識點某些情況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,今天是第3天。 本計劃一共28期,每期重點攻...
摘要:本期推薦文章從作用域鏈談閉包,由于微信不能訪問外鏈,點擊閱讀原文就可以啦。推薦理由這是一篇譯文,深入淺出圖解作用域鏈,一步步深入介紹閉包。作用域鏈的頂端是全局對象,在全局環(huán)境中定義的變量就會綁定到全局對象中。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周開始前端進階的第二期,本周的主題是作用域閉包,今天是第6天。 本...
摘要:使用上一篇文章的例子來說明下自由變量進階期深入淺出圖解作用域鏈和閉包訪問外部的今天是今天是其中既不是參數,也不是局部變量,所以是自由變量。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第7天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進階計...
摘要:閉包面試題解由于作用域鏈機制的影響,閉包只能取得內部函數的最后一個值,這引起的一個副作用就是如果內部函數在一個循環(huán)中,那么變量的值始終為最后一個值。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第二期,本周的主題是作用域閉包,今天是第8天。 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了...
摘要:首次運行代碼時,會創(chuàng)建一個全局執(zhí)行上下文并到當前的執(zhí)行棧中。執(zhí)行上下文的創(chuàng)建執(zhí)行上下文分兩個階段創(chuàng)建創(chuàng)建階段執(zhí)行階段創(chuàng)建階段確定的值,也被稱為。 (關注福利,關注本公眾號回復[資料]領取優(yōu)質前端視頻,包括Vue、React、Node源碼和實戰(zhàn)、面試指導) 本周正式開始前端進階的第一期,本周的主題是調用堆棧,,今天是第一天 本計劃一共28期,每期重點攻克一個面試重難點,如果你還不了解本進...
閱讀 2985·2021-11-23 09:51
閱讀 2798·2021-11-11 16:55
閱讀 2907·2021-10-14 09:43
閱讀 1393·2021-09-23 11:22
閱讀 1034·2019-08-30 11:04
閱讀 1663·2019-08-29 11:10
閱讀 955·2019-08-27 10:56
閱讀 3101·2019-08-26 12:01