1. 浅拷贝的实现
1.1引用赋值(首层深)
function shallowClone(source) {
var target = {};
for(var i in source) {
if (source.hasOwnProperty(i)) {
target[i] = source[i];
}
}
return target;
}
1.2 Object.assign()
var x = {
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
var y = Object.assign({}, x);
console.log(y.b.f === x.b.f); // true
2. 深拷贝的实现
2.1 JSON的parse和stringify
JSON.stringify 是将一个 JavaScript 值转成一个 JSON 字符串。
JSON.parse 是将一个 JSON 字符串转成一个 JavaScript 值或对象。
我们可以通过上述两种转换的结合来进行深拷贝
const originArray = [1,2,3,4,5];
const cloneArray = JSON.parse(JSON.stringify(originArray));
console.log(cloneArray === originArray); // false
const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
const cloneObj = JSON.parse(JSON.stringify(originObj));
console.log(cloneObj === originObj); // false
cloneObj.a = 'aa';
cloneObj.c = [1,1,1];
cloneObj.d.dd = 'doubled';
console.log(cloneObj); // {a:'aa',b:'b',c:[1,1,1],d:{dd:'doubled'}};
console.log(originObj); // {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
不过这只能适用于一些简单的情况,比如对象中带有方法就不行,因为undefined、function、Symbol会在转换过程中被忽略。
2.2 递归
function deepClone(source) {
const target = source.constructor === Array?[]:{}
for (const key in source) {
if (source.hasOwnProperty(key)) {
// 如果是对象就递归,不是就直接赋值
if (source[key] && typeof source[key] === 'object') {
target[key] = source[key].constructor === Array ? [] : {}
target[key] = deepClone(source[key])
} else {
target[key] = source[key]
}
}
}
return target
}
const originObj = {a:'a',b:'b',c:[1,2,3],d:{dd:'dd'}};
const cloneObj = deepClone(originObj)
console.log(cloneObj === originObj); // false
2.3 contact和slice
contact是连接两个或多个数组的方法,我们通过实例可以发现它是一个首层深拷贝的方法。
const originArray = [1,[1,2,3],{a:1}];
const cloneArray = originArray.concat();
console.log(cloneArray === originArray); // false
cloneArray[1].push(4);
cloneArray[2].a = 2;
console.log(originArray); // [1,[1,2,3,4],{a:2}]
经过测试,slice同样也是首层深拷贝。