在前端开发的面试中,深拷贝和浅拷贝的区别是一个高频考点。
今天,我们就来详细探讨一下深拷贝和浅拷贝的区别,以及它们的实现方式。
一、深拷贝和浅拷贝的区别
浅拷贝的特点
只拷贝第一层:浅拷贝只会复制对象的第一层属性。
基本数据类型拷贝值:对于基本数据类型(如 number、string、boolean),直接拷贝值。
引用数据类型拷贝引用:对于引用数据类型(如 object、array),拷贝的是引用而不是实际对象。
深拷贝的特点
多层递归拷贝:深拷贝会递归地复制对象的所有层级。
基本数据类型拷贝值:对于基本数据类型,直接拷贝值。
引用数据类型创建新对象:对于引用数据类型,创建一个新的对象,并递归地将原对象的属性复制到新对象中。
const obj = {
a: 1,
b: [1, 2, 3],
c: {
d: 4,
e: 5
}
}
const newObj = deepClone(obj);
console.log(newObj);
/**
打印结果:
{
a: 1,
b: [1, 2, 3],
c: {
d: 4,
e: 5
}
}
*/
对于浅拷贝来说:
obj.b === newObj.b(引用相同)
obj.c === newObj.c(引用相同)
而对于深拷贝来说,newObj 的所有属性都是新的引用,与原对象完全独立。
二、浅拷贝的实现方式
-
- 展开运算符
使用 ES6 提供的展开运算符(...)可以实现浅拷贝:
- 展开运算符
const newObj = { ...obj };
-
- Object.assign
Object.assign 是一个静态方法,可以将一个或多个对象的可枚举自有属性合并到目标对象中:
- Object.assign
const newObj = Object.assign({}, obj1, obj2, ...);
-
- for..in + Object.prototype.hasOwnProperty
通过 for..in 循环和 hasOwnProperty 方法手动实现浅拷贝:
- for..in + Object.prototype.hasOwnProperty
function shallowClone(obj) {
const newObj = {};
for (let key in obj) {
if (obj.hasOwnProperty(key)) {
newObj[key] = obj[key];
}
}
return newObj;
}
三、深拷贝的实现方式
-
- JSON.parse + JSON.stringify
通过 JSON.stringify 将对象序列化为 JSON 字符串,再通过 JSON.parse 将其解析为新的对象:
- JSON.parse + JSON.stringify
const newObj = JSON.parse(JSON.stringify(obj));
缺点:
无法处理循环引用。
不支持 function 和 undefined。
无法复制某些对象类型(如 Date、RegExp、Map、Set 等)。
2. 使用第三方库
使用 lodash 等第三方库可以轻松实现深拷贝:
const _ = require('lodash');
const newObj = _.cloneDeep(obj);
-
- 手动实现深拷贝
通过递归手动实现深拷贝:
- 手动实现深拷贝
const isObj = (target) => typeof target === 'object' && target !== null;
function deepClone(obj, hash = new WeakMap()) {
if (!isObj(obj)) return obj;
if (hash.has(obj)) return hash.get(obj);
const target = new obj.constructor();
hash.set(obj, target);
Object.keys(obj).forEach((key) => {
target[key] = deepClone(obj[key], hash);
});
return target;
}
五、总结
深拷贝和浅拷贝是前端开发中常见的概念,掌握它们的区别和实现方式对于面试和实际开发都非常重要。
希望这篇文章能帮助你更好地理解深拷贝和浅拷贝!如果你对上述内容有任何疑问,欢迎在评论区留言讨论!