1. 对象拷贝办法
1.1 JSON.parse
和 JSON.stringify
办法
利用 JSON.stringify
和JSON.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); // 4
console.log(newObj.e); // undefined
console.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); // 4
console.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); // 4
console.log(newObj.b.c); // 4
1.4 解构赋值
利用解构赋值办法进行的是浅拷贝。
var obj = {
a: 1,
b: {c: 1}
}
var newObj = {...obj}
newObj.b.c = 2
console.log(obj.b.c) // 2
console.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); // 4
console.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;
}