引用型別賦值給另一個引用型別,它們只是都是指向的同一個位址,操作間會互相影響。
深拷貝,就是重新分配空間,讓它跟著之前的物件或陣列不受影響。
淺拷貝就是等同於引用型別的賦值。
var a={banner:{size:1,weight:'0.5kg'}};
var b={apple:{size:1},banner:{size:3}};
$.extend(true,a,b)=>{banner:{size:3,weight:'0.5kg'},apple:{size:1}};
$.extend(a,b)=>{banner:{size:3},apple:{size:1}};
我看過jquery源碼,深拷貝是要進行遞歸的。
但是我不理解,跟互相影響有什麼關係,還是說我上面的概念理解錯誤
给我你的怀抱2017-05-19 10:35:54
淺拷貝
僅對object頂層鍵進行遍歷和重新賦值(給對應的引用),例如:
var a = {
x: {
name: 'x',
value: 10,
},
y: 10,
o: {},
}
var b = {
x: {
name: 'x2',
value: 20,
},
y: {
name: 'y2',
value: 20,
},
z: {}
}
$.extend(a, b)
這個過程裡面,從b中取出所有頂層元素,即b.x, b.y, b.z,然後將它們一一賦值給a對應的鍵,所以最後a就有了新的a.x, a.y, a.z,同時,a.o還保留在a中,這時a.x === b.x, a.y === b.y, a.z === b.z,因為它們都是指向同一個物件的引用。既然是引用,當你操作a.x的時候,例如a.x.name = 'x3',那麼b.x.name也變成了'x3'。
深拷貝
深拷貝將深入物件元素的末層進行重新賦值,而非引用。就拿上面的a,b舉例,執行:
$.extend(true, a, b)
將會深入b內部進行遍歷,拿每一個節點的值與a對應(一模一樣)的節點進行比較,如果不同則為a開闢儲存空間,把值賦進去,如果a不存在這個節點,就為它創建後賦值進去。 a的第一層子節點跟b第一層不存在相等關係,連==都不成立。
深拷貝後,a原有的一些節點會保留下來,b給過去的節點會覆蓋或增加,但是和b之間不存在任何引用關係,所以修改a的任何一個節點,都不會影響b。這在一些數據處理的時候非常有用,為了不影響原始數據,需要在處理數據之前深拷貝一份再進行處理。
深拷貝的時候,陣列的索引號碼被當作鍵名對待,所以陣列元素會被修改,而不是被加入到原始資料中。如:
var a = [
{
x: 1,
},
{
x: 2,
},
]
var b = [
{
y: 2
},
]
$.extend(true, a, b)
將會得到:
var a = [
{
x: 1,
y: 2
},
{
x: 2,
},
]
b的第一個原始被合併到a的第一個元素裡面去了,這個合併是因為數組按照元素的索引號作為鍵來操作。所以,合併數組不能用extend,而應該考慮用merge或concat。