javascript - 引用物件賦值 深淺拷貝 jquery.extend
PHPz
PHPz 2017-05-19 10:33:54
0
2
988

引用型別賦值給另一個引用型別,它們只是都是指向的同一個位址,操作間會互相影響。
深拷貝,就是重新分配空間,讓它跟著之前的物件或陣列不受影響。
淺拷貝就是等同於引用型別的賦值。

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源碼,深拷貝是要進行遞歸的。
但是我不理解,跟互相影響有什麼關係,還是說我上面的概念理解錯誤

PHPz
PHPz

学习是最好的投资!

全部回覆(2)
给我你的怀抱

淺拷貝

僅對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。

滿天的星座

只是名字重複了,和深拷貝/淺拷貝沒有關係。應該叫遞歸拷貝比較合適。

熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板