返回
JavaScript 深浅拷贝你真的会用吗?
前端
2023-09-20 02:00:29
在 JavaScript 中,拷贝对象或数组时,我们可以选择深拷贝或浅拷贝。那么,深拷贝和浅拷贝有什么区别?又该如何选择合适的拷贝方式呢?
深拷贝与浅拷贝
浅拷贝 是指只拷贝对象的引用,而不是拷贝对象本身。这意味着,如果我们对浅拷贝的对象进行修改,那么原始对象也会受到影响。
深拷贝 是指不仅拷贝对象的引用,还会拷贝对象本身。这意味着,如果我们对深拷贝的对象进行修改,那么原始对象不会受到影响。
浅拷贝的实现方法
JavaScript 中实现浅拷贝的方法有很多,最常见的方法是使用 Object.assign()
方法。
const obj1 = { name: 'John', age: 30 };
const obj2 = Object.assign({}, obj1);
obj2.name = 'Mary';
console.log(obj1); // { name: 'John', age: 30 }
console.log(obj2); // { name: 'Mary', age: 30 }
深拷贝的实现方法
实现深拷贝的方法有很多,最常见的方法是使用递归或循环。
递归 :
function deepCopy(obj) {
if (typeof obj !== 'object' || obj === null) {
return obj;
}
if (Array.isArray(obj)) {
return obj.map(deepCopy);
}
const newObj = {};
for (const key in obj) {
newObj[key] = deepCopy(obj[key]);
}
return newObj;
}
循环 :
function deepCopy(obj) {
const queue = [{ obj, parent: null, key: null }];
const visited = new WeakMap();
const result = {};
while (queue.length > 0) {
const { obj, parent, key } = queue.shift();
if (visited.has(obj)) {
parent[key] = visited.get(obj);
continue;
}
visited.set(obj, obj);
if (Array.isArray(obj)) {
parent[key] = [];
obj.forEach((item, index) => {
queue.push({ obj: item, parent: parent[key], key: index });
});
continue;
}
if (typeof obj === 'object' && obj !== null) {
parent[key] = {};
for (const key in obj) {
queue.push({ obj: obj[key], parent: parent[key], key });
}
continue;
}
parent[key] = obj;
}
return result;
}
何时使用深拷贝,何时使用浅拷贝?
浅拷贝 适用于以下场景:
- 当我们需要拷贝一个对象或数组,并且不希望修改原始对象或数组时。
- 当我们需要拷贝一个对象或数组,并且知道对象或数组中不包含任何引用类型的数据时。
深拷贝 适用于以下场景:
- 当我们需要拷贝一个对象或数组,并且希望修改拷贝后的对象或数组时。
- 当我们需要拷贝一个对象或数组,并且知道对象或数组中包含引用类型的数据时。
总结
深拷贝和浅拷贝是 JavaScript 中常用的两种拷贝方式。了解不同实现方法和实现粒度的优劣及其适合的场景,可以帮助我们选择最合适的拷贝方式,避免潜在的陷阱。