JS深拷贝
js对象是引用类型,对于=
直接赋值的场景,复制的是存在栈内存里面的引用指针,并不是存放在堆内存中的内容,当对一个对象下面的属性值进行修改时,所有的都会变化。
/** 浅复制 **/
let person1 = {
'name': 'Jack',
'age': 29
};
let person2 = person1;
person2.name = "Kai";
console.log(person1.name); //'Kai'
console.log(person2.name); //'Kai'
浅拷贝
可以解决一般问题,如果对象只有一层,可以使用浅拷贝。以下几种方式可以实现浅拷贝:
Object.assign()
...
扩展运算符
Object.assign
Object.assign
let a = {
age: 1,
};
let b = Object.assign({}, a);
a.age = 2;
console.log(b.age); // 1
...
扩展运算符
...
扩展运算符let a = {
age: 1,
};
let b = { ...a };
a.age = 2;
console.log(b.age); // 1
深复制
深复制想实现把对象里面属性值也给复制,当修改复制后的对象某个属性值时,原对象对应的属性值不会被修改。
有以下几种:
JSON的全局对象
parse
和stringify
方法(有限制)遍历实现深度复制
JSON的全局对象parse
和stringify
方法
parse
和stringify
方法这种方法好处是非常简单易用,对于Number
, String
,Object
等来说基本实现。但是坏处也显而易见,对于正则表达式类型、函数类型等无法进行深拷贝(而且会直接丢失相应的值)。还有一点不好的地方是它会抛弃对象的constructor,也就是深复制之后,无论这个对象原本的构造函数是什么,在深复制之后都会变成Object
。
function deepClone(source){
return JSON.parse(JSON.stringify(source));
}
let person1 = {
'name': 'Jack',
'age': 29,
'fn':function (){
console.log('fn')
},
'reg': new RegExp('e')
};
let person2 = deepClone(person1);
console.log(person1.name); // 'Jack'
console.log(person2.name); // 'Kai'
console.log(person2.fn); // undefined
console.log(person2.reg); // Object
递归遍历实现深复制
通过遍历到对象的每一层,实现深度复制,对引用类型中的function,reg,Date特殊处理。推荐使用
function deepClone(obj, c) {
let newObj = c || {}
for (let i in obj) {
// 引用类型拷贝
if (obj[i] instanceof Object) {
if (obj[i] instanceof Function) {
// function
newObj[i] = function () {
return obj[i].call(this, ...arguments);
}
} else if (obj[i] instanceof RegExp) {
// reg
newObj[i] = new RegExp(obj[i]);
} else if (obj[i] instanceof Date) {
// Date
newObj[i] = new Date(obj[i]);
} else {
// 普通对象和数组
newObj[i] = obj[i] instanceof Array ? [] : {};
deepClone(obj[i], newObj[i]);
}
} else {
// 普通类型拷贝
newObj[i] = obj[i];
}
}
return newObj;
}
Last updated