淺析JS中的堆記憶體與棧記憶體

來源:互聯網
上載者:User

標籤:分析   應該   lock   com   不可變   容量   因此   實值型別   的區別   

最近跟著組裡的大佬面試碰到這麼一個問題,

Q:說說var、let、const的區別
A:balabalabalabla...
Q:const定義的值能改嗎?
A:你逗我?不能吧

不知道各位看官怎麼想?答案是部分能改,部分不能改。const定義的基本類型不能改變,但是定義的對象是可以通過修改對象屬性等方法來改變的。如,

>>> const a = 1>>> a<<< 1>>> a = 2<<< VM1750:1 Uncaught TypeError: Assignment to constant variable.    at <anonymous>:1:3    (anonymous) @ VM1750:1>>> const b = {}>>> b<<< {}>>> b.name = 1>>> b<<< {name: 1}>>> b = {}<<< VM1785:1 Uncaught TypeError: Assignment to constant variable.    at <anonymous>:1:4

const不是定義常量嗎?為什麼還能改?這就是我們今天要說的重點~

js中的堆記憶體與棧記憶體

在js引擎中對變數的儲存主要有兩種位置,堆記憶體和棧記憶體

和java中對記憶體的處理類似,棧記憶體主要用於儲存各種基本類型的變數,包括Boolean、Number、String、Undefined、Null,**以及物件變數的指標,這時候棧記憶體給人的感覺就像一個線性排列的空間,每個小單元大小基本相等。

而堆記憶體主要負責像對象Object這種變數類型的儲存,如

棧記憶體中的變數一般都是已知大小或者有範圍上限的,算作一種簡單儲存。而堆記憶體儲存的物件類型資料對於大小這方面,一般都是未知的。個人認為,這也是為什麼null作為一個object類型的變數卻儲存在棧記憶體中的原因。

因此當我們定義一個const對象的時候,我們說的常量其實是指標,就是const對象對應的堆記憶體指向是不變的,但是堆記憶體中的資料本身的大小或者屬性是可變的。而對於const定義的基礎變數而言,這個值就相當於const對象的指標,是不可變。

既然知道了const在記憶體中的儲存,那麼const、let定義的變數不能二次定義的流程也就比較容易猜出來了,每次使用const或者let去初始化一個變數的時候,會首先遍曆當前的記憶體棧,看看有沒有重名變數,有的話就返回錯誤。

說到這裡,有一個十分很容易忽略的點,之前也是自己一直沒有注意的就是,使用new關鍵字初始化的之後是不儲存在棧記憶體中的。為什麼呢?new大家都知道,根據建構函式產生新執行個體,這個時候產生的是對象,而不是基本類型。再看一個例子

var a = new String('123')var b = String('123')var c = '123'console.log(a==b, a===b, b==c, b===c, a==c, a===c)  >>> true false true true true falseconsole.log(typeof a)>>> 'object'

我們可以看到new一個String,出來的是對象,而直接字面量賦值和原廠模式出來的都是字串。但是根據我們上面的分析大小相對固定可預期的即便是對象也可以儲存在棧記憶體的,比如null,為啥這個不是呢?再繼續看

var a = new String('123')var b = new String('123')console.log(a==b, a===b)>>> false false

很明顯,如果a,b是儲存在棧記憶體中的話,兩者應該是明顯相等的,就像null === null是true一樣,但結果兩者並不相等,說明兩者都是儲存在堆記憶體中的,指標指向不一致。

說到這裡,再去想一想我們常說的實值型別和參考型別其實說的就是棧記憶體變數和堆記憶體變數,再想想值傳遞和引用傳遞、深拷貝和淺拷貝,都是圍繞堆棧記憶體展開的,一個是處理值,一個是處理指標。

記憶體配置和記憶體回收

一般來說棧記憶體線性有序儲存,容量小,系統分配效率高。而堆記憶體首先要在堆記憶體新分配儲存地區,之後又要把指標儲存到棧記憶體中,效率相對就要低一些了。
記憶體回收方面,棧記憶體變數基本上用完就回收了,而推記憶體中的變數因為存在很多不確定的引用,只有當所有調用的變數全部銷毀之後才能回收。

繼續往下思考的話,其中還有很多的東西需要去學習,今天先到這裡,後續再來補充。

話說~NaN會不會也是儲存在堆記憶體中的呢?大家想想吧,歡迎大家來一起討論討論~文中如有錯誤歡迎指出~

淺析JS中的堆記憶體與棧記憶體

相關文章

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.