Object.assign 是淺拷貝還是深拷貝?實現深拷貝的方法有哪些?

Object.assign() 方法用于將所有可枚舉屬性的值從一個或多個源對象復制到目標對象。它將返回目標對象。
如果目標對象中的屬性具有相同的鍵,則屬性將被源對象中的屬性覆蓋。后面的源對象的屬性將類似地覆蓋前面的源對象的屬性。

Object.assign 方法只會拷貝源對象自身的并且可枚舉的屬性到目標對象。該方法使用源對象的[[Get]]和目標對象的[[Set]],所以它會調用相關 getter 和 setter。因此,它分配屬性,而不僅僅是復制或定義新的屬性。如果合并源包含getter,這可能使其不適合將新屬性合并到原型中。為了將屬性定義(包括其可枚舉性)復制到原型,應使用Object.getOwnPropertyDescriptor()和Object.defineProperty() 。

String類型和 Symbol 類型的屬性都會被拷貝。

在出現錯誤的情況下,例如,如果屬性不可寫,會引發TypeError,如果在引發錯誤之前添加了任何屬性,則可以更改target對象。

Object.assign 不會在那些source對象值為 null或 undefined 的時候拋出錯誤。

針對深拷貝,需要使用其他辦法,因為 Object.assign()拷貝的是屬性值。假如源對象的屬性值是一個對象的引用,那么它也只指向那個引用。也就是說,如果對象的屬性值為簡單類型(如string, number),通過Object.assign({},srcObj);得到的新對象為深拷貝;如果屬性值為對象或其它引用類型,那對于這個對象而言其實是淺拷貝的

深拷貝的幾種實現方法

JSON.stringify 和 JSON.parse

用 JSON.stringify 把對象轉換成字符串,再用 JSON.parse 把字符串轉換成新的對象。

可以轉成 JSON 格式的對象才能使用這種方法,如果對象中包含 function 或 RegExp 這些就不能用這種方法了。

//通過js的內置對象JSON來進行數組對象的深拷貝
function deepClone(obj) {
  let _obj = JSON.stringify(obj);
  let objClone = JSON.parse(_obj);
  return objClone;
}

Object.assign()拷貝

當對象中只有一級屬性,沒有二級屬性的時候,此方法為深拷貝,但是對象中有對象的時候,此方法,在二級屬性以后就是淺拷貝。

通過jQuery的extend方法實現深拷貝
let $ = require('jquery');
let obj1 = {
   a: 1,
   b: {
     f: {
       g: 1
     }
   },
   c: [1, 2, 3]
};
let obj2 = $.extend(true, {}, obj1);
lodash.cloneDeep()實現深拷貝
let _ = require('lodash');
let obj1 = {
    a: 1,
    b: { f: { g: 1 } },
    c: [1, 2, 3]
};
let obj2 = _.cloneDeep(obj1);

使用遞歸的方式實現深拷貝

function _deepClone(source) {
  let target;
  if (typeof source === 'object') {
    target = Array.isArray(source) ? [] : {}
    for (let key in source) {
      if (source.hasOwnProperty(key)) {
        if (typeof source[key] !== 'object') {
          target[key] = source[key]
        } else {
          target[key] = _deepClone(source[key])
        }
      }
    }
  } else {
    target = source
  }
  return target
}
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。