#说到拷贝对象,大家可能会先想到Object.assign
这个方法,但是它并不是那么完美,它只会拷贝一层对象,如果对象里面还有对象它就引用了原来的对象。具体看下面代码
- 一层拷贝没任何问题
let obj = {
aa: 11
}
let newObj = Object.assign({}, obj);
obj.aa = 22;
console.log(newObj.aa); //11
console.log(obj.aa); //22
- 多层拷贝就变成引用了
let obj = {
aa: 11,
bb: {
cc: 22
}
}
let newObj = Object.assign({}, obj);
obj.bb.cc = 33;
console.log(newObj.bb.cc); //33
console.log(obj.bb.cc); //33
像上面这样拷贝对象我们叫浅拷贝,其实我们也可以通过for-in循环来模拟浅拷贝
let obj = {
aa: 11,
bb: {
cc: 22
}
}
let newObj = {};
for (const key in obj) {
newObj[key] = obj[key];
}
下面简单实现一个对象的深拷贝
function clone(Obj) {
var buf;
if (Obj instanceof Array) {
buf = []; // 创建一个空的数组
var i = Obj.length;
while (i--) {
buf[i] = clone(Obj[i]);
}
return buf;
} else if (Obj instanceof Object) {
buf = {}; // 创建一个空对象
for (var k in Obj) { // 为这个对象添加新的属性
buf[k] = clone(Obj[k]);
}
return buf;
} else {
return Obj;
}
}
比较详细的写法可以像下面这样
let obj = {aa: 11, bb: {cc: [0, [1]]}}
function copyObj(options) {
return copy(options)
}
function copyAry(ary) {
let newAry = []
for (const item of ary) {
let value = item;
if (Object.prototype.toString.call(value) === "[object Object]") value = copyObj(value);
if (Object.prototype.toString.call(value) === "[object Array]") value = copyAry(value);
newAry.push(value);
}
return newAry;
}
function copy(obj) {
let newObj = {};
for (const key in obj) {
let value = obj[key];
if (Object.prototype.toString.call(value) === "[object Object]") value = copyObj(value);
if (Object.prototype.toString.call(value) === "[object Array]") value = copyAry(value);
newObj[key] = value;
}
return newObj;
}
let newObj = copyObj(obj);
// 测试
obj.bb.cc[1][0] = 666;
console.log(newObj.bb.cc[1][0]) //1
console.log(obj.bb.cc[1][0]) //666