1、介紹
創建數據的時候就會佔用內容、內存主要開闢了兩類空間
1. 堆(進程,線程共享)
- 大小不固定,可隨時增加
- 不允許js直接訪問堆內存
- 存儲引用數據類型
- 按引用訪問
- 存儲的值大小不定,可動態調整
- 主要用來存放對象
- 空間大,但是運行效率相對較低
- 無序存儲,可根據引用直接獲取
2. 棧(線程) - 創建的時候就確定了大小,故可能會溢出
- 按照順序存放 先進後出
- 存儲基礎數據類
- 按值訪問
- 存儲的值大小固定
- 由系統自動分配內存空間
- 空間小,運行效率高
- 棧中的DOM,ajax,setTimeout會依次進入到隊列中,當棧中代碼執行完畢後,再將隊列中的事件放到執行棧中依次執行。
複雜數據類型(Object、[數組、對象])創建的時候 開闢的 堆內存
基本數據類型(number、string等6種)創建的時候 開闢的 棧內容
2、比較
var str=new String('abc');
var str='abc';
同樣是創建兩個字符串,第一種是用new關鍵字來新建String對象,對象會存放在堆中,每調用一次就會創建一個新的對象;
而第二種是在棧中,棧中存放值‘abc’和對值的引用。推薦使用第二種方式創建多個’abc’字符串,這種寫法在內存中只存在一個值,有利於節省內存空間。
同時它可以在一定程度上提高程序的運行速度,因爲存儲在棧中,其值可以共享,並且由於棧訪問更快,所以對於性能的提高大有裨益。
而第一種方式每次都在堆中創建一個新的String對象,而不管其字符串值是否相等及是否有必要創建新對象,從而加重了程序的負擔。並且堆的訪問速度慢,對程序性能的影響也大。
另外,出於邏輯運算的考慮,當對兩個變量進行比較時,使用堆和棧存儲就會有差異
1) 例如下面的代碼,實際只比較棧中的值:
var str1='abc';
var str2='abc';
alert(str1==str2); // true
alert(str1===str2); // true
不管是邏輯等於和邏輯全等運算都返回true,可以看出str1和str2指向同一個值。
2)例如下面的代碼,實際只比較堆中的值:
var str1=new String('abc');
var str2=new String('abc');
alert(str1==str2); // false
alert(str1===str2); // false
不管是邏輯等於還是邏輯全等都返回false,可以看出str1和str2指向的不是同一個對象。
3)例如下面的代碼,比較堆和棧中的值:
var str1=new String('abc');
var str2='abc';
alert(str1==str2); // true
alert(str1===str2); // false
在進行邏輯等於和邏輯全等運算時,會首先將變量轉成相同的數據類型,然後進行對比。變量str1和str2的數據類型雖然不同,但比較運算還是返回true。但邏輯全等運算與邏輯等於運算不同,它會對數據類型進行比較,看是否是引用的同一個數據。
3、總結
- 棧內存是有限度的可以自動釋放,堆內存無限不會自動釋放,運行程序的時候,每個線程分配一個棧,每個進程分配一個堆
- 棧存放基本類型的變量、函數、對象變量指針,堆存放對象
- 放在棧裏面的變量,只要值一樣就可以全等,棧佔內存較小,會自動釋放值,值爲null,放在堆裏面的變量,值相等(應爲會默認轉成相同數據類型進行對比),全等=會比較是否引用一個數據故不等,不會自動釋放值
- 棧中數據可以共享,若是兩個變量值一樣,可以一起指向那個值