(關注福利,關注本公衆號回覆[資料]領取優質前端視頻,包括Vue、React、Node源碼和實戰、面試指導)javascript
本週正式開始前端進階的第一期,本週的主題是調用堆棧,今天是第3天。前端
本計劃一共28期,每期重點攻克一個面試重難點,若是你還不瞭解本進階計劃,點擊查看前端進階的破冰之旅java
前端基礎進階(一):內存空間詳細圖解 ,因爲微信不能訪問外鏈,點擊閱讀原文就能夠啦。webpack
今天介紹的是JS內存空間,瞭解內存空間中的堆和棧原理對於理解JS閉包、Event Loop等有很大幫助,本文使用圖解形式,即便是第一次接觸本文的讀者也很容易理解堆棧。文末提供了一個思考題,歡迎加羣討論。git
堆棧的內容和執行順序我就不說了,前面兩篇已經介紹過了。github
【進階1-1期】理解JavaScript 中的執行上下文和執行棧web
【進階1-2期】JavaScript深刻之執行上下文棧和變量對象面試
可是今天補充一個知識點:某些狀況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。算法
對於下面的遞歸就會無限制的執行下去,直到超出調用堆棧的實際大小,這個是瀏覽器定義的。跨域
function foo() { foo(); } foo();
如今正式開始今天的主題,內存空間詳解
棧的結構就是後進先出(LIFO),若是讀過前面兩篇文章應該是至關熟悉了。文中使用乒乓球盒子的結構來解釋。
處於盒子中最頂層的乒乓球5,它必定是最後被放進去,但能夠最早被使用。而咱們想要使用底層的乒乓球1,就必須將上面的4個乒乓球取出來,讓乒乓球1處於盒子頂層。
堆數據結構是一種樹狀結構。它的存取數據的方式與書架和書很是類似。咱們只須要知道書的名字就能夠直接取出書了,並不須要把上面的書取出來。JSON格式的數據中,咱們存儲的key-value
能夠是無序的,由於順序的不一樣並不影響咱們的使用,咱們只須要關心書的名字。
隊列是一種先進先出(FIFO)的數據結構,這是事件循環(Event Loop)的基礎結構,事件循環咱們會在第8期詳解介紹。
首先咱們應該知道內存中有棧和堆,那麼變量應該存放在哪裏呢,堆?棧?
在計算機的數據結構中,棧比堆的運算速度快,Object是一個複雜的結構且能夠擴展:數組可擴充,對象可添加屬性,均可以增刪改查。將他們放在堆中是爲了避免影響棧的效率。而是經過引用的方式查找到堆中的實際對象再進行操做。因此查找引用類型值的時候先去棧查找再去堆查找。
問題1:
var a = 20; var b = a; b = 30; // 這時a的值是多少?
問題2:
var a = { name: '前端開發' } var b = a; b.name = '進階'; // 這時a.name的值是多少
問題3:
var a = { name: '前端開發' } var b = a; a = null; // 這時b的值是多少
如今來解答一下,三個問題的答案分別是20
、‘進階’
、{ name: '前端開發' }
b.name
的值後,相應的a.name
也就發生了改變。null
是基本類型,a = null
以後只是把a存儲在棧內存中地址改變成了基本類型null,並不會影響堆內存中的對象,因此b的值不受影響。JavaScript的內存生命週期是
JavaScript有自動垃圾收集機制,最經常使用的是經過標記清除的算法來找到哪些對象是再也不繼續使用的,使用a = null
其實僅僅只是作了一個釋放引用的操做,讓 a 本來對應的值失去引用,脫離執行環境,這個值會在下一次垃圾收集器執行操做時被找到並釋放。
在局部做用域中,當函數執行完畢,局部變量也就沒有存在的必要了,所以垃圾收集器很容易作出判斷並回收。可是全局變量何時須要自動釋放內存空間則很難判斷,所以在開發中,須要儘可能避免使用全局變量。
var a = {n: 1}; var b = a; a.x = a = {n: 2}; a.x // 這時 a.x 的值是多少 b.x // 這時 b.x 的值是多少
前端基礎進階(一):內存空間詳細圖解
每週面試重難點計劃以下,若有修改會通知你們。每週一期,爲期半年,準備明年跳槽的小夥伴們能夠把本公衆號置頂了。
本人Github連接以下,歡迎各位Star
http://github.com/yygmind/blog
我是木易楊,網易高級前端工程師,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!
若是你想加羣討論每期面試知識點,公衆號回覆[加羣]便可