深入理解JavaScript中的深拷贝与浅拷贝
在前端面试过程中,JS中的深浅拷贝是个非常经典的考点
面试官经常借此来考察候选人对数据类型、内存分配和对象引用的理解程度
本文将系统地介绍深浅拷贝的区别、原理和常见实现方式,并通过代码实例加以阐述
一、什么是浅拷贝(Shallow Copy)?
浅拷贝是指创建一个新的对象或数组,这个新对象对原对象的属性值进行精确的复制
然而,如果原对象的属性值是引用类型(如对象或数组),则浅拷贝只复制其引用,而不是具体的值
示例
let original = { name: "Alice", hobbies: ["reading", "coding"] };
let shallowCopy = Object.assign({}, original);
shallowCopy.name = "Bob";
shallowCopy.hobbies.push("swimming");
console.log(original); // { name: "Alice", hobbies: ["reading", "coding", "swimming"] }
console.log(shallowCopy); // { name: "Bob", hobbies: ["reading", "coding", "swimming"] }
可以看出,更改浅拷贝对象的引用类型属性时,原对象也随之发生了变化。
二、什么是深拷贝(Deep Copy)?
深拷贝会完全复制原对象中所有的值,包括嵌套的对象和数组,从而创建一个完全独立的新对象,新旧对象之间不存在共享引用
示例
常见的深拷贝方式之一是利用JSON进行序列化:
let original = { name: "Alice", hobbies: ["reading", "coding"] };
let deepCopy = JSON.parse(JSON.stringify(original));
// 修改深拷贝对象
deepCopy.name = "Bob";
deepCopy.hobbies.push("swimming");
console.log(original); // { name: "Alice", hobbies: ["reading", "coding"] }
console.log(deepCopy); // { name: "Bob", hobbies: ["reading", "coding", "swimming"] }
此时可以看到,修改深拷贝对象时,原对象不会受到任何影响。
三、浅拷贝与深拷贝的实现方式
浅拷贝常见方法
使用Object.assign()
使用扩展运算符…
使用数组方法如Array.slice()
或Array.concat()
let arr = [1, 2, 3];
let shallowArr = arr.slice();
shallowArr.push(4);
console.log(arr); // [1, 2, 3]
console.log(shallowArr); // [1, 2, 3, 4]
深拷贝常见方法
使用JSON.parse(JSON.stringify())(简单快速,但有局限性,如无法处理函数、Date、RegExp等)
使用递归函数实现深拷贝
function deepClone(obj) {
if (typeof obj !== 'object' || obj === null) return obj;
let copy = Array.isArray(obj) ? [] : {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
copy[key] = deepClone(obj[key]);
}
}
return copy;
}
let original = { a: 1, b: { c: 2 } };
let clone = deepClone(original);
clone.b.c = 3;
console.log(original); // { a: 1, b: { c: 2 } }
console.log(clone); // { a: 1, b: { c: 3 } }
四、面试中常见问题与注意点
-
如何判断何时使用深拷贝或浅拷贝?
如果不想原数据被修改,尤其是处理嵌套复杂对象时,使用深拷贝 -
JSON序列化深拷贝的缺陷是什么?
JSON方法无法处理函数、Symbol、RegExp、Date、循环引用等复杂结构 -
如何解决循环引用问题?
在深拷贝时维护一个WeakMap或Map,记录已复制的对象,避免重复引用
五、总结
理解深浅拷贝不仅能够帮助你避免开发过程中的坑,也能够让你在前端面试中脱颖而出
希望各位大家在学习路上不断精进,持续成长!