首頁  >  文章  >  web前端  >  一起了解JS中的深拷貝與淺拷貝

一起了解JS中的深拷貝與淺拷貝

青灯夜游
青灯夜游轉載
2020-07-09 15:07:432280瀏覽

一起了解JS中的深拷貝與淺拷貝

淺拷貝

#淺拷貝是物件的逐位複製。建立一個新對象,該對象具有原始對像中值的精確副本。如果物件的任何欄位是對其他物件的引用,則只複製引用位址,即,複製記憶體位址。

大白話講就是,淺拷貝是對物件位址的複製,並沒有開闢新的棧,也就是複製的結果是兩個物件指向同一個位址,修改其中一個物件的屬性,則另一個物件的屬性也會改變。

深拷貝

深拷貝複製所有字段,並複製字段所指向的動態分配記憶體。深拷貝發生在物件及其引用的物件被複製時。

大白話講就是,深拷貝則是開闢新的棧,兩個物件對應兩個不同的位址,修改一個物件的屬性,不會改變另一個物件的屬性。

Look See See 範例

#淺拷貝:它將X的參考複製到Y中。因此,XY的位址是相同的,也就是說它們指向相同的記憶體位置。

深拷貝:複製X的所有成員,為Y分配不同的記憶體位置,然後將複製的成員分配給Y,實現深拷貝。這樣,如果X消失了,Y在記憶體中仍然有效。

考慮下面的程式碼:

var employeeDetailsOriginal = {  
  name: '前端小智', 
  age: 18,
  Profession: '前端开发' 
};

假設你想要建立一個這個物件的副本,這樣即使原始值被改變了,仍然可以透過副本得到原始物件的值。

我會這樣做:

var employeeDetailsDuplicate = employeeDetailsOriginal; // 浅拷贝

如果咱們改變一個值:

employeeDetailsDuplicate.name = '王大治';

這樣操作,咱們的原始物件employeeDetailsOriginal 的屬性 name 也會跟著改變,因為這裡有一個淺拷貝。這樣咱們就取得不到原始物件的值了。所以這種拷貝做法是不對的。

但是,透過使用原始employeeDetailsOriginal變數的屬性來建立一個全新的變量,就可以建立一個深拷貝副本。

var employeeDetailsDuplicate = {
  name: employeeDetailsOriginal.name,
  age: employeeDetailsOriginal.age, 
  Profession: employeeDetailsOriginal.Profession
}; // 深拷贝

現在,如果更改employeeDetailsDuplicate.name,它只會影響employeeDetailsDuplicate,而不會影響employeeDetailsOriginal

一起了解JS中的深拷貝與淺拷貝

談Object.assign()

Object.assign()是咱們常用到的方法,其實這個方法就是淺拷貝。但是它又有一點特殊的地方,就是可以處理第一層的深拷貝。

var employeeDetailsOriginal = {  
  name: '前端小智',
  family: {
    name: '前端大家庭'
  }
};

var employeeDetailsDuplicate = Object.assign({}, employeeDetailsOriginal );

employeeDetailsDuplicate.name = '王大治'
employeeDetailsDuplicate.family.name = '后端大家庭'

console.log(employeeDetailsOriginal ); 
// { name: "前端小智", family: {name: "后端大家庭"} }
console.log(employeeDetailsDuplicate);
// { name: "王大冶智", family: {name: "后端大家庭"} }

看上面的例子,屬性name的值並沒有跟著變,但是屬性中familyname的值跟著變了。

如何實作深拷貝

唯一的作法就是複製這個物件。

对于简单的JSON对象,最简单的方法是

var objectIsNew  = JSON.parse(JSON.stringify(objectIsOld));

//如果使用jQuery,可以使用:

// 浅拷贝
var objectIsNew = jQuery.extend({}, objectIsOld);

// 深拷贝
var objectIsNew = jQuery.extend(true, {}, objectIsOld);

純JS方法來深拷貝物件(非最佳方法)

function keepCloning(objectpassed) {
  if (objectpassed=== null || typeof objectpassed!== 'object') {
    return objectpassed;
  }
  
  // 临时存储原始的obj的构造
  var temporary_storage = objectpassed.constructor(); 
  for (var key in objectpassed) {
    temporary_storage[key] = keepCloning(objectpassed[key]);
  }
   return temporary_storage;
}

var employeeDetailsOriginal = {  
  name: '前端小智', 
  age: 18, 
  Profession: '前端开发' 
};

var employeeDetailsDuplicate = (keepCloning(employeeDetailsOriginal));

employeeDetailsOriginal.name = "前端大治";

console.log(employeeDetailsOriginal);
console.log(employeeDetailsDuplicate);

#總結

了解深拷貝也不只是為了應付面試題,在實際開發中也是非常有用的。例如後台回傳了一堆數據,你需要對這堆數據做操作,但多人開發情況下,你是沒辦法明確這堆數據是否有其它功能也需要使用,直接修改可能會造成隱性問題,深拷貝能幫你更安全安心的去操作數據,根據實際情況來使用深拷貝,大概就是這個意思。

本文轉載自:https://segmentfault.com/a/1190000020438346

相關教學推薦:JavaScript影片教學

以上是一起了解JS中的深拷貝與淺拷貝的詳細內容。更多資訊請關注PHP中文網其他相關文章!

陳述:
本文轉載於:segmentfault.com。如有侵權,請聯絡admin@php.cn刪除