1. 对象拷贝办法

1.1 JSON.parseJSON.stringify办法

利用JSON.stringifyJSON.parse办法进行的是深拷贝,但无奈拷贝函数和undefined,也无奈拷贝对象原型链上的属性和办法。

var obj = {  a: 1,  b: 2,  c: {    d: 4,    // 在解析成 JSON 字符串时,undefined 不解析    e: undefined,    // null 在 JSON 字符串中就是 null => "f": null    f: null  },  f: function () { console.log('function'); }};var newObj = JSON.parse(JSON.stringify(obj));console.log(newObj.c.d); // 4console.log(newObj.e); // undefinedconsole.log(newObj.f); // undefined

1.2 for-in循环

利用for-in循环进行的是浅拷贝,只拷贝根本类型的数据,对于援用类型的数据,只复制了指针。

var obj = {  a: 1,  b: {    c: 3  }};var newObj = {};for (var key in obj) {  newObj[key] = obj[key];}newObj.b.c = 4;console.log(obj.b.c); // 4console.log(newObj.b.c); // 4

1.3 Object.assign办法

利用Object.assign办法进行的是浅拷贝,拷贝源对象中的可枚举和自有属性。

var obj = {  a: 1,  b: {    c: 3  }};var newObj = {};Object.assign(newObj, obj);newObj.b.c = 4;console.log(obj.b.c); // 4console.log(newObj.b.c); // 4

1.4 解构赋值

利用解构赋值办法进行的是浅拷贝。

var obj = {  a: 1,  b: {    c: 1  }}var newObj = {...obj}newObj.b.c = 2console.log(obj.b.c) // 2console.log(newObj.b.c) // 2

2. 手写对象深拷贝办法

2.1 ES5 实现对象深拷贝

function deepClone (origin, target) {  var _tar = target || {}    for (var key in origin) {    if (origin.hasOwnProperty(key)) {      if (typeof origin[key] === 'object' && origin[key] !== null) {        _tar[key] = Object.prototype.toString.call(origin[key]) === '[object Array]' ? [] : {};        deepClone(origin[key], _tar[key]);      } else _tar[key] = origin[key];    }  }  return _tar}var obj = {  a: 1,  b: 2,  c: {    d: 4,    e: 5  },  f: function () { console.log('function'); }};var newObj = {};deepClone(obj, newObj);console.log(newObj.c.d); // 4console.log(newObj.f); // undefined

2.2 ES6 实现对象深拷贝

function deepClone (origin) {  if (origin == undefined || typeof origin !== 'object') return origin;    if (origin instanceof Date) return new Date(origin);  if (origin instanceof RegExp) return new RegExp(origin);    const target = new origin.constructor();    for (let key in origin) {    if (origin.hasOwnProperty(key)) {      target[key] = deepClone(origin[key]);    }  }    return target;}

可能实现对象深拷贝,但当呈现循环援用时会导致死循环。因而须要利用WeakMap保留已进行过拷贝的对象,避免死循环。

function deepClone (origin, hashMap = new WeakMap()) {  if (origin == undefined || typeof origin !== 'object') return origin;  if (origin instanceof Date) return new Date(origin);  if (origin instanceof RegExp) return new RegExp(origin);    const hashVal = hashMap.get(origin);  if (hashVal) return hashVal;    const target = new origin.constructor();  hashMap.set(origin, target);    for (let key in origin) {    if (origin.hasOwnProperty(key)) {      target[key] = deepClone(origin[key]);    }  }    return target;}