JS的內存空間分爲棧(stack)、堆(heap)、池(通常也會歸類爲棧中)。其中棧存放變量,堆存放複雜對象,池存放常量,因此也叫常量池前端
基本數據類型保存在棧內存中,由於基本數據類型佔用空間小、大小固定,經過按值來訪問,屬於被頻繁使用的數據。bash
Array,Function,Object...能夠認爲除了上文提到的基本數據類型之外,全部類型都是引用數據類型。閉包
引用數據類型存儲在堆內存中。由於引用數據類型佔據空間大、大小不固定。 若是存儲在棧中,將會影響程序運行的性能。所以, 引用數據類型只是在棧中存儲了一個指針,該指針指向堆中的該實體。 當解釋器尋找引用值時,會首先檢索其在棧中的地址,從棧取得地址在堆中得到實體。函數
let a = 20;
let b = a;
b = 30;
console.log(b); // 30
console.log(a); // 20
複製代碼
棧遵循 後進先出 原則:聲明一個變量,屢次賦值取最後一個值。post
a、b 都是基本數據類型,它們的值是存儲在棧內存中的,a、b 分別有各自獨立的棧空間, 因此修改了 b 的值之後,a 的值並不會發生變化。性能
let m = { a: 10, b: 20 };
let n = m;
n.a = 15;
console.log(m.a); //15
複製代碼
m、n都是引用數據類型,棧內存中存放的地址指向堆內存中的對象。 引用類型的複製會爲新的變量自動分配一個新的值保存在棧內存中, 但只是引用類型的一個地址指針而已,實際指向的是仍是同一個對象。也就是說m、n是同一個地址指針,而指針是沒有變的。ui
棧內存中變量通常在它的當前執行環境結束就會被銷燬被垃圾回收制回收, 而堆內存中的變量則不會,由於不肯定其餘的地方是否是還有一些對它的引用。 堆內存中的變量只有在全部對它的引用都結束的時候纔會被回收。spa
閉包中的變量並不保存中棧內存中,而是保存在堆內存中。 這也就解釋了函數調用以後爲何閉包還能引用到函數內的變量。指針