存儲問題:
深拷貝和淺拷貝的主要區別:在內存中的存儲類型(堆和棧)不一樣
堆:動態分配的內存,大小不定也不會自動釋放
棧:自動分配的內存,由系統自動釋放
數據類型:javascript
基本數據類型:
javascript的基本數據類型5種:undefined null number string boolean
存儲位置java
棧。緣由:數據大小肯定,內存空間大小能夠分配,是直接按值存放的。
值是否可變?數組
基本數據類型值不可變,javascript中的原始值(undefined、null、布爾值、數字和字符串)與對象(包括數組和函數)有着根本區別。原始值是不可更改的:任何方法都沒法更改(或「突變」)一個原始值。對 數字和布爾值來講顯然如此 —— 改變數字的值自己就說不通,而對字符串來講就不那麼明顯了,由於字符串看起來像由字符組成的數組,咱們指望能夠經過指定索引來假改字符串中的字符。實際上,javascript 是禁止這樣作的。字符串中全部的方法看上去返回了一個修改後的字符串,實際上返回的是一個新的字符串值。
基本類型的比較函數
基本類型的比較是值的比較,只要兩個變量的值相等就認爲他們是相等的。 比較最好用 === ,由於 == 會進行類型轉換,例如:var a = 1; var b= true;if(a==b) 則會返回true
引用數據類型(object):
堆。變量其實是存放在棧內存中的一個指針,這個指針指向堆內存中的地址,每一個空間大小不同,要根據狀況進行特定的分配。post
引用類型值可變
var a = [1,2,3];
a[1] = 5;
console.log(a[1]); // 5spa
引用類型的比較是引用的比較
因此每次咱們對 js 中的引用類型進行操做的時候,都是操做其對象的引用(保存在棧內存中的指針),因此比較兩個引用類型,是看其的引用是否指向同一個對象。
var a = [1,2,3];
var b = [1,2,3];
console.log(a === b); // false
雖然變量 a 和變量 b 都是表示一個內容爲 1,2,3 的數組,可是其在內存中的位置不同,也就是說變量 a 和變量 b 指向的不是同一個對象,因此他們是不相等的。指針
傳值和傳址
基本數據類型賦值code
基本數據類型的賦值(=)是在內存中新開闢一段棧內存,而後再把再將值賦值到新的棧中。 var a = 10; var b = a; a ++; console.log(a); // 11 console.log(b); // 10
引用數據類型賦值對象
可是引用類型的賦值是傳址。只是改變指針的指向,例如,也就是說引用類型的賦值是對象保存在棧中的地址的賦值,這樣的話兩個變量就指向同一個對象,所以二者之間操做互相有影響。 var a = {}; // a保存了一個空對象的實例 var b = a; // a和b都指向了這個空對象 a.name = 'jozo'; console.log(a.name); // 'jozo' console.log(b.name); // 'jozo' b.age = 22; console.log(b.age); // 22 console.log(a.age); // 22 console.log(a == b);// true
淺拷貝
那麼賦值和淺拷貝有什麼區別呢,咱們看下面這個例子:blog
var obj1 = { 'name' : 'zhangsan', 'age' : '18', 'language' : [1,[2,3],[4,5]], }; var obj2 = obj1; var obj3 = shallowCopy(obj1); function shallowCopy(src) { var dst = {}; for (var prop in src) { if (src.hasOwnProperty(prop)) { dst[prop] = src[prop]; } } return dst; } obj2.name = "lisi"; obj3.age = "20"; obj2.language[1] = ["二","三"]; obj3.language[2] = ["四","五"]; console.log(obj1); //obj1 = { // 'name' : 'lisi', // 'age' : '18', // 'language' : [1,["二","三"],["四","五"]], //}; console.log(obj2); //obj2 = { // 'name' : 'lisi', // 'age' : '18', // 'language' : [1,["二","三"],["四","五"]], //}; console.log(obj3); //obj3 = { // 'name' : 'zhangsan', // 'age' : '20', // 'language' : [1,["二","三"],["四","五"]], //};
先定義個一個原始的對象 obj1,而後使用賦值獲得第二個對象 obj2,而後經過淺拷貝,將 obj1 裏面的屬性都賦值到 obj3 中。也就是說:
而後咱們改變 obj2 的 name 屬性和 obj3 的 name 屬性,能夠看到,改變賦值獲得的對象 obj2 同時也會改變原始值 obj1,而改變淺拷貝獲得的的 obj3 則不會改變原始對象 obj1。這就能夠說明賦值獲得的對象 obj2 只是將指針改變,其引用的仍然是同一個對象,而淺拷貝獲得的的 obj3 則是從新建立了新對象。
然而,咱們接下來來看一下改變引用類型會是什麼狀況呢,我又改變了賦值獲得的對象 obj2 和淺拷貝獲得的 obj3 中的 language 屬性的第二個值和第三個值(language 是一個數組,也就是引用類型)。結果見輸出,能夠看出來,不管是修改賦值獲得的對象 obj2 和淺拷貝獲得的 obj3 都會改變原始數據。
這是由於淺拷貝只複製一層對象的屬性,並不包括對象裏面的爲引用類型的數據。因此就會出現改變淺拷貝獲得的 obj3 中的引用類型時,會使原始數據獲得改變。
深拷貝
深拷貝是對對象以及對象的全部子對象進行拷貝。
怎麼進行深拷貝?
思路就是遞歸調用剛剛的淺拷貝,把全部屬於對象的屬性類型都遍歷賦給另外一個對象便可
zepto深拷貝的例子還須要繼續瞭解深拷貝的實現方案。