更新:謝謝你們的支持,最近折騰了一個博客官網出來,方便你們系統閱讀,後續會有更多內容和更多優化,猛戳這裏查看javascript
------ 如下是正文 ------前端
本期的主題是調用堆棧,本計劃一共28期,每期重點攻克一個面試重難點,若是你還不瞭解本進階計劃,文末點擊查看所有文章。java
若是以爲本系列不錯,歡迎點贊、評論、轉發,您的支持就是我堅持的最大動力。webpack
堆棧的內容和執行順序我就不說了,前面兩篇已經介紹過了。git
可是今天補充一個知識點:某些狀況下,調用堆棧中函數調用的數量超出了調用堆棧的實際大小,瀏覽器會拋出一個錯誤終止運行。github
對於下面的遞歸就會無限制的執行下去,直到超出調用堆棧的實際大小,這個是瀏覽器定義的。web
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.com/yygmind/blo…,內有優質前端資料,以爲不錯點個star。
我是木易楊,網易高級前端工程師,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!