一、棧(stack)和堆(heap)javascript
stack爲自動分配的內存空間,它由系統自動釋放;而heap則是動態分配的內存,大小也不必定會自動釋放html
二、數據類型java
JS分兩種數據類型:正則表達式
js的六或七大數據類型:Number, String, Boolean, Undefined , Null , Object, Symbol(ES6)數組
基本數據類型:Number、String、Boolean、Null、 Undefined、Symbol(ES6),這些類型能夠直接操做保存在變量中的實際值。函數
引用數據類型:Object(在JS中除了基本數據類型之外的都是對象,數據是對象,函數是對象,正則表達式是對象)性能
三、基本數據類型(存放在棧中)大數據
基本數據類型是指存放在棧中的簡單數據段,數據大小肯定,內存空間大小能夠分配,它們是直接按值存放的,因此能夠直接按值訪問。基本數據類型的值是沒有辦法添加屬性和方法的 spa
var a = 10; var b = a; b = 20; console.log(a); // 10值 console.log(b); // 20值
下圖演示了這種基本數據類型賦值的過程:指針
四、引用數據類型(存放在堆內存中的對象,每一個空間大小不同,要根據狀況進行特定的配置)
引用類型是存放在堆內存中的對象,變量實際上是保存的在棧內存中的一個指針(保存的是堆內存中的引用地址),這個指針指向堆內存。
引用類型數據在棧內存中保存的其實是對象在堆內存中的引用地址。經過這個引用地址能夠快速查找到保存中堆內存中的對象
var obj1 = new Object(); var obj2 = obj1; obj2.name = "我有名字了"; console.log(obj1.name); // 我有名字了
說明這兩個引用數據類型指向了同一個堆內存對象。obj1賦值給obj2,實際上這個堆內存對象在棧內存的引用地址複製了一份給了obj2,可是實際上他們共同指向了同一個堆內存對象,因此修改obj2其實就是修改那個對象,因此經過obj1訪問也能訪問的到。
var a = [1,2,3,4,5]; var b = a; // 傳址 ,對象中傳給變量的數據是引用類型的,會存儲在堆中; var c = a[0]; //傳值,把對象中的屬性/數組中的數組項賦值給變量,這時變量C是基本數據類型,存儲在棧內存中;改變棧中的數據不會影響堆中的數據 alert(b);//1,2,3,4,5 alert(c);//1 //改變數值 b[4] = 6; c = 7; alert(a); //[1,2,3,4,6];
alert(a[0]);//1
從上面咱們能夠得知,當我改變b中的數據時,a中數據也發生了變化;可是當我改變c的數據值時,a卻沒有發生改變。
這就是傳值與傳址的區別。由於a是數組,屬於引用類型,因此它賦予給b的時候傳的是棧中的地址(至關於新建了一個不一樣名「指針」),而不是堆內存中的對象。而c僅僅是從a堆內存中獲取的一個數據值,並保存在棧中。因此b修改的時候,會根據地址回到a堆中修改,c則直接在棧中修改,而且不能指向a堆內存中。
最後: 總結基本數據類型和引用數據類型區別
一、聲明變量時內存分配不一樣
*原始類型:在棧中,由於佔據空間是固定的,能夠將他們存在較小的內存中-棧中,這樣便於迅速查詢變量的值
*引用類型:存在堆中,棧中存儲的變量,只是用來查找堆中的引用地址。
這是由於:引用值的大小會改變,因此不能把它放在棧中,不然會下降變量查尋的速度。相反,放在變量的棧空間中的值是該對象存儲在堆中的地址。地址的大小是固定的,因此把它存儲在棧中對變量性能無任何負面影響
二、不一樣的內存分配帶來不一樣的訪問機制
在javascript中是不容許直接訪問保存在堆內存中的對象的,因此在訪問一個對象時,首先獲得的是這個對象在堆內存中的地址,而後再按照這個地址去得到這個對象中的值,這就是傳說中的按引用訪問。
而原始類型的值則是能夠直接訪問到的。
三、複製變量時的不一樣
1)原始值:在將一個保存着原始值的變量複製給另外一個變量時,會將原始值的副本賦值給新變量,此後這兩個變量是徹底獨立的,他們只是擁有相同的value而已。
2)引用值:在將一個保存着對象內存地址的變量複製給另外一個變量時,會把這個內存地址賦值給新變量,