【進階1-3期】JavaScript深刻以內存空間詳細圖解

(關注福利,關注本公衆號回覆[資料]領取優質前端視頻,包括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期詳解介紹。

變量的存放

首先咱們應該知道內存中有棧和堆,那麼變量應該存放在哪裏呢,

  • 一、基本類型 --> 保存在內存中,由於這些類型在內存中分別佔有固定大小的空間,經過按值來訪問。基本類型一共有6種:Undefined、Null、Boolean、Number 、String和Symbol
  • 二、引用類型 --> 保存在內存中,由於這種值的大小不固定,所以不能把它們保存到棧內存中,但內存地址大小的固定的,所以保存在堆內存中,在棧內存中存放的只是該對象的訪問地址。當查詢引用類型的變量時, 先從棧中讀取內存地址, 而後再經過地址找到堆中的值。對於這種,咱們把它叫作按引用訪問。

在計算機的數據結構中,棧比堆的運算速度快,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: '前端開發' }

  • 對於問題1,a、b都是基本類型,它們的值是存儲在棧中的,a、b分別有各自獨立的棧空間,因此修改了b的值之後,a的值並不會發生變化。
  • 對於問題2,a、b都是引用類型,棧內存中存放地址指向堆內存中的對象,引用類型的複製會爲新的變量自動分配一個新的值保存在變量對象中,但只是引用類型的一個地址指針而已,實際指向的是同一個對象,因此修改b.name的值後,相應的a.name也就發生了改變。
  • 對於問題3,首先要說明的是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 的值是多少

參考

前端基礎進階(一):內存空間詳細圖解

解讀 JavaScript 之引擎、運行時和堆棧調用

JavaScript變量——棧內存or堆內存

往期文章查看

每週計劃安排

每週面試重難點計劃以下,若有修改會通知你們。每週一期,爲期半年,準備明年跳槽的小夥伴們能夠把本公衆號置頂了。

  • 【進階1期】 調用堆棧
  • 【進階2期】 做用域閉包
  • 【進階3期】 this全面解析
  • 【進階4期】 深淺拷貝原理
  • 【進階5期】 原型Prototype
  • 【進階6期】 高階函數
  • 【進階7期】 事件機制
  • 【進階8期】 Event Loop原理
  • 【進階9期】 Promise原理
  • 【進階10期】Async/Await原理
  • 【進階11期】防抖/節流原理
  • 【進階12期】模塊化詳解
  • 【進階13期】ES6重難點
  • 【進階14期】計算機網絡概述
  • 【進階15期】瀏覽器渲染原理
  • 【進階16期】webpack配置
  • 【進階17期】webpack原理
  • 【進階18期】前端監控
  • 【進階19期】跨域和安全
  • 【進階20期】性能優化
  • 【進階21期】VirtualDom原理
  • 【進階22期】Diff算法
  • 【進階23期】MVVM雙向綁定
  • 【進階24期】Vuex原理
  • 【進階25期】Redux原理
  • 【進階26期】路由原理
  • 【進階27期】VueRouter源碼解析
  • 【進階28期】ReactRouter源碼解析

交流

本人Github連接以下,歡迎各位Star

http://github.com/yygmind/blog

我是木易楊,網易高級前端工程師,跟着我每週重點攻克一個前端面試重難點。接下來讓我帶你走進高級前端的世界,在進階的路上,共勉!

若是你想加羣討論每期面試知識點,公衆號回覆[加羣]便可

相關文章
相關標籤/搜索