棧(stack)和堆(heap) stack為自動分配的記憶體空間,它由系統自動釋放;而heap則是動態分配的記憶體,大小不定也不會自動釋放。 基本類型和引用類型 基本類型:存放在棧記憶體中的簡單數據段,數據大小確定,記憶體空間大小可以分配。 基本數據類型有Undefined、Null、Boolean、Nu ...
棧(stack)和堆(heap)
stack為自動分配的記憶體空間,它由系統自動釋放;而heap則是動態分配的記憶體,大小不定也不會自動釋放。
基本類型和引用類型
基本類型:存放在棧記憶體中的簡單數據段,數據大小確定,記憶體空間大小可以分配。
基本數據類型有Undefined、Null、Boolean、Number 和 String,他們的值是直接存放在棧中;
引用類型:存放在堆記憶體中的對象的值,由地址指針與值組成,地址保存在棧中,實際的值保存在堆中,堆中的每個空間大小不一樣,根據情況進行特定的分配。當我們需要訪問引用類型(如對象,數組,函數等)的值時,首先從棧中獲得該對象的地址指針,然後再從堆記憶體中取得所需的數據;
var s='str',t= 0,floatNum=1.1; var obj={ a:10, b:'Joel', c:function(){ console.log('function'); } }
如上所示:
基本數據類型值是保存在棧中,引用類型的對象引用是保存在棧中,值是保存在堆中;
總結
聲明變數時不同的記憶體分配:
基本類型:存儲在棧(stack)中的簡單數據段,它們的值直接存儲在變數訪問的位置。這是因為基本類型占據的空間是固定的,所以可將他們存儲在較小的記憶體區域 – 棧中,這樣存儲便於迅速查詢變數的值。
引用類型:存儲在堆(heap)中的對象,存儲在棧中的值是一個指針(point)用於指向存儲對象的記憶體地址,這是因為引用類型值的大小會改變,所以不能把它放在棧中,否則會降低變數查尋的速度。相反存在棧中的值是該對象地址而地址的大小是固定的,所以把它存儲在棧中對變數性能無任何影響。
不同的記憶體分配機制也帶來了不同的訪問機制
在javascript中是不允許直接訪問保存在堆記憶體中的對象的,所以在訪問一個對象時,首先訪問記憶體棧得到這個對象在記憶體堆中的地址,然後再按照這個地址去獲得這個對象中的值,這就是傳說中的按引用訪問,而基本類型的值則是直接記憶體棧中。
複製變數時的不同
基本類型:在將一個保存著原始值的變數複製給另一個變數時,會將原始值的副本賦值給新變數,此後這兩個變數是完全獨立的,他們只是擁有相同的value而已。
引用類型:在將一個保存著對象記憶體地址的變數複製給另一個變數時,會把這個記憶體地址賦值給新變數,也就是說這兩個變數都指向了堆記憶體中的同一個對象,他們中任何一個作出的改變都會反映在另一個身上。(這裡要理解的一點就是,複製對象時並不會在堆記憶體中新生成一個一模一樣的對象,只是多了一個保存指向這個對象指針的變數)多了一個指針。
參數傳遞的不同(把實參複製給形參的過程)
ECMAScript中所有函數的參數都是按值來傳遞的,但是為什麼涉及到原始類型與引用類型的值時仍然有區別呢?還不就是因為記憶體分配時的差別。
基本數據類型:只是把變數里的值複製一個副本然後傳遞給參數,之後參數和這個變數互不影響。
引用類型:因為它傳遞的值是記憶體地址,所以都是指向同一個對象;