Object--对象拷贝

476 阅读2分钟

1、浅拷贝

  • 原始遍历

问题:对象中的对象还是引用的形式,只复制了 mainObj 的可枚举属性,属性描述符不能被复制,objCopy 对象具有一个新的 Object.prototype方法

function copy(mainObj)  {
if (null == mainObj || Object.prototype.toString.call(mainObj)!=='[object Object]') {
  return mainObj
};
  let objCopy = { }; 
  let key;

  for ( key in mainObj ) {
    if(mainObj.hasOwnProperty(key)){// 不遍历原型链, 仅拷贝自身的属性
         objCopy[key] = mainObj[key];   
     }
  }
  return objCopy;
}

const mainObj = {
  a: 2,
  b: 5,
  c: {
    x: 7,
    y: 4,
  },
  d: function d() {
    return 3;
  }
}

let a =  copy(mainObj) ;
console.log(a)
a.c.x=0;
a.d = function newD(){}
console.log(a)
console.log(mainObj)
//a输出结果
{
  a: 2,
  b: 5,
  c: {
    x: 0,
    y: 4
  },
  d: function newD(){} 
}
//mainObj输出结果
 {
  a: 2,
  b: 5,
  c:  {
    x: 0, //不同<---------------------------------
    y: 4
  },
  d: function d() { 
    return 3;
  }
}

  • Object.assign()

Object.assign() 方法用于将从一个或多个源对象中的所有可枚举的属性值复制到目标对象。可以用于复制对象的方法
问题:对象中的对象还是引用的形式,原型链上的属性和不可枚举的属性不能复制,循环引用对象(以下有例子)也是浅拷贝

let obj = {
  a: 1,
  b: {
    c: 2,
  },
}
let newObj = Object.assign({}, obj);

newObj.b.c = 30;
console.log(obj); // { a: 10, b: { c: 30} }<---------------------------------
console.log(newObj); // { a: 20, b: { c: 30} }
  • 使用展开操作符(…)

问题:数组中的对象还是引用的形式

const array = [
 "a",
 "c",
 "d", {
   four: 4
 },
];
const newArray = [...array];
newArray[3].four=9
console.log(array);
//结果
["a", "c", "d",  {
 four: 9
}]

没有对象嵌套对象可以考虑用以上三个

2、深拷贝

  • 使用递归遍历

function deepClone(obj) {
    var copy;

    // Handle number, boolean, string, null and undefined
    if (null == obj || "object" != typeof obj) return obj;

    // Handle Date
    if (obj instanceof Date) {
        copy = new Date();
        copy.setTime(obj.getTime());
        return copy;
    }

    // Handle Array
    if (obj instanceof Array) {
        copy = [];
        for (var i = 0, len = obj.length; i < len; i++) {
            copy[i] = deepClone(obj[i]);
        }
        return copy;
    }

    // Handle Object
    if (obj instanceof Object) {
        copy = {};
        for (var attr in obj) {
            if (obj.hasOwnProperty(attr)) copy[attr] = deepClone(obj[attr]);
        }
        return copy;
    }

    throw new Error("Unable to copy obj! Its type isn't supported.");
}

  • 对象没有function,没有循环引用

    JSON.parse(JSON.stringify(对象))
// circular object
let obj = { 
  a: 'a',
  b: { 
    c: 'c',
    d: 'd',
  },
}

obj.c = obj.b;
obj.b.c = obj.c;
let newObj = JSON.parse(JSON.stringify(obj));
console.log(newObj); 
//结果
"error"
"TypeError: Converting circular structure to JSON
    --> starting at object with constructor 'Object'
    --- property 'c' closes the circle
    at JSON.stringify (<anonymous>)
    at bikibet.js:15:30
    at https://static.jsbin.com/js/prod/runner-4.1.7.min.js:1:13924
    at https://static.jsbin.com/js/prod/runner-4.1.7.min.js:1:10866"

感谢作者,以下原文出处juejin.cn/post/684490…