這裏先說兩個概念:一、堆(heap)二、棧(stack)
堆 是堆內存的簡稱。
棧 是棧內存的簡稱。
說到堆棧,咱們講的就是內存的使用和分配了,沒有寄存器的事,也沒有硬盤的事。
各類語言在處理堆棧的原理上都大同小異。堆是動態分配內存,內存大小不一,也不會自動釋放。棧是自動分配相對固定大小的內存空間,並由系統自動釋放。javascript
javascript的基本類型就5種:Undefined、Null、Boolean、Number和String,它們都是直接按值存儲在棧中的,每種類型的數據佔用的內存空間的大小是肯定的,並由系統自動分配和自動釋放。這樣帶來的好處就是,內存能夠及時獲得回收,相對於堆來講,更加容易管理內存空間。java
javascript中其餘類型的數據被稱爲引用類型的數據 : 如對象(Object)、數組(Array)、函數(Function) …,它們是經過拷貝和new出來的,這樣的數據存儲於堆中。其實,說存儲於堆中,也不太準確,由於,引用類型的數據的地址指針是存儲於棧中的,當咱們想要訪問引用類型的值的時候,須要先從棧中得到對象的地址指針,而後,在經過地址指針找到堆中的所須要的數據。數組
說來也是形象,棧,線性結構,後進先出,便於管理。堆,一個混沌,雜亂無章,方便存儲和開闢內存空間
傳值與傳址數據結構
var arr1 = [1,2,5,8]; var arr2 = arr1 ; var str1 = arr1[2]; console.log(arr2);//1,2,5,8 console.log(str1);//5 arr2[4] = 99; str1 = 6; console.log(arr1);//1,2,5,8,99 console.log(arr1[2]);//5
上方例子得知,當我改變arr2中的數據時,arr1中數據也發生了變化,當改變str1的數據值時,arr1卻沒有發生改變。爲何?這就是傳值與傳址的區別。函數
由於arr1是數組,屬於引用類型,因此它賦予給arr2的時候傳的是棧中的地址(至關於新建了一個不一樣名「指針」),而不是堆內存中的對象的值。str1獲得的是一個基本類型的賦值,所以,str1僅僅是從arr1堆內存中獲取了一個數值,並直接保存在棧中。arr一、arr2都指向同一塊堆內存,arr2修改的堆內存的時候,也就會影響到arr1,str1是直接在棧中修改,而且不能影響到arr1堆內存中的數據。ui
淺拷貝和深拷貝spa
上邊說到的賦值方式就是淺拷貝,那麼什麼叫做深拷貝呢?就是要將arr1的每一個基本類型的數據都遍歷一遍,依次的賦值給arr2的對應字段。避免產生由於地址引用帶來的問題。指針
var arr1 = [1,2,5,8]; var arr2 = []; for(var i=0;i<arr1.length;i++){ arr2[i]=arr1[i]; }; console.log(arr2)//1,2,5,8 arr2[4]=99; console.log(arr2)//1,2,5,8,99 console.log(arr1)//1,2,5,8
javascript面向對象的語言自己在處理對象和非對象上就進行了劃分,從數據結構的角度來說,對象就是棧的指針和堆中的數值。code