关于JavaScript的深拷贝和浅拷贝,一般有如下几种实现方式:
浅拷贝
1. Object.assign()
方法
该方法用于将所有可枚举属性从一个或多个源对象复制到目标对象。如果源对象中有与目标对象相同的属性,那么目标对象对应属性的值将被覆盖。由于该方法只会进行浅拷贝,因此如果源对象中的属性是一个对象或数组等复合类型,那么目标对象和源对象的属性将会引用同一个对象。
const obj = { a: 1, b: { c: 2 } };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1, b: { c: 2 } }
copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }
copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 4 } } 对象的属性也被更改了。
2. 手写简易的浅拷贝函数
使用 for ... in
循环遍历原对象的所有可枚举属性,并将其复制到目标对象上。与 Object.assign()
类似,如果属性是一个对象或数组等复合类型,那么目标对象和源对象的属性将会引用同一个对象。
function shallowCopy(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
const copy = Array.isArray(obj) ? [] : {};
for (const key in obj) {
if (obj.hasOwnProperty(key)) copy[key] = obj[key];
}
return copy;
}
const obj = { a: 1, b: { c: 2 } };
const copy = shallowCopy(obj);
console.log(copy); // { a: 1, b: { c: 2 } }
copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }
copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 4 } } 对象的属性也被更改了。
深拷贝
1. JSON.parse + JSON.stringify
JSON.parse 方法用来解析 JSON 字符串,返回对应的 JavaScript 对象或值。JSON.stringify 方法用来将 JavaScript 对象或值转换为 JSON 字符串。
将一个对象进行深拷贝,可以先将对象转化成 JSON 字符串,再将其转化成对象,这样就可以获得一个与原对象完全独立的新对象。
需要注意的是,该方法只适用于对象的属性值是可遍历的,如果出现循环引用的情况,则会抛出异常。
const obj = { a: 1, b: { c: 2 } };
const copy = JSON.parse(JSON.stringify(obj));
console.log(copy); // { a: 1, b: { c: 2 } }
copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }
copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 2 } } 对象的属性没有被更改。
2. 递归实现深拷贝函数
对于一个对象来说,我们需要遍历对象的所有属性,如果属性是一个基本类型,直接赋值即可。如果属性是一个对象或数组等复合类型,那么就需要递归调用深拷贝函数,直到遍历完所有的属性。
function deepCopy(obj, memo = new WeakMap()) {
if (typeof obj !== 'object' || obj === null) return obj;
if (memo.has(obj)) return memo.get(obj);
const copy = Array.isArray(obj) ? [] : {};
memo.set(obj, copy);
for (const key in obj) {
if (obj.hasOwnProperty(key)) copy[key] = deepCopy(obj[key], memo);
}
return copy;
}
const obj = { a: 1, b: { c: 2 } };
const copy = deepCopy(obj);
console.log(copy); // { a: 1, b: { c: 2 } }
copy.a = 3; // 修改副本
console.log(copy); // { a: 3, b: { c: 2 } }
console.log(obj); // { a: 1, b: { c: 2 } }
copy.b.c = 4; // 修改副本中的对象的属性
console.log(copy); // { a: 3, b: { c: 4 } }
console.log(obj); // { a: 1, b: { c: 2 } } 对象的属性没有被更改。
以上介绍了针对JavaScript的深拷贝和浅拷贝的实现方式,建议在开发过程中根据实际场景选择合适的方式。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS实现深拷贝和浅拷贝的方式详解 - Python技术站