JSON.parse(JSON.stringify()) 与 lodash 的 cloneDeep:深度拷贝的比力与基础知识
JSON.parse(JSON.stringify()) 与 lodash 的 cloneDeep:深度拷贝的比力与基础知识在 JavaScript 开发中,**深拷贝(Deep Copy)**是一个常见需求,尤其是在处理复杂对象和嵌套数据布局时。JSON.parse(JSON.stringify(obj)) 和 lodash 的 cloneDeep 函数都是实现深拷贝的常用方法。本文将详细探讨这两种方法的区别、各自的优缺点以及干系的基础知识,帮助你根据详细需求选择符合的深拷贝方式。
深拷贝 vs 浅拷贝
在讨论详细的深拷贝方法之前,起首需要明白 深拷贝 和 浅拷贝 的区别。
[*]浅拷贝(Shallow Copy):
[*]只复制对象的第一层属性。
[*]如果属性是引用范例(如对象、数组),复制的是引用,两个对象共享同一个内存地点,修改此中一个会影响另一个。
[*]深拷贝(Deep Copy):
[*]递归复制对象的全部层级。
[*]复制后的对象与原对象独立,修改一个不会影响另一个。
JSON.parse(JSON.stringify(obj)) 详解
工作原理
JSON.parse(JSON.stringify(obj)) 通过以下步调实现深拷贝:
[*]JSON.stringify(obj):
[*]将 JavaScript 对象转换为 JSON 字符串。
[*]只能序列化可罗列的自有属性,不支持函数、undefined、Symbol、Infinity、NaN 等特别值。
[*]会将对象的布局和数据转换成 JSON 格式的字符串。
[*]JSON.parse(jsonString):
[*]将 JSON 字符串分析为一个新的 JavaScript 对象。
[*]从而获得原对象的深拷贝。
长处
[*]简单易用:
[*]仅利用原生 JavaScript 方法,无需引入外部库。
[*]语法简便,一行代码实现深拷贝。
[*]实用于简单对象:
[*]对于布局简单的对象(如普通 JSON 数据),效果精良。
缺点
[*] 数据范例限:
[*]无法复制函数:函数在序列化过程中会被忽略。
[*]无法复制特别值:
[*]undefined、Symbol 会被转换为 null。
[*]Infinity、NaN 会被转换为 null 或 0。
[*]Date 对象被转换为字符串。
[*]RegExp、Map、Set 等复杂对象无法准确复制。
[*]循环引用:
[*]如果对象内部存在循环引用(如 obj.a = obj),会抛堕落误。
[*] 性能开销:
[*]对于大型对象或深度嵌套的对象,序列化和分析过程会带来较大的性能开销。
[*] 不可处理函数和原型链:
[*]无法保存对象的方法(函数)和继续自原型链的属性。
示例
const original = {
name: "Alice",
age: 30,
hobbies: ["reading", "gaming"],
address: {
city: "Wonderland",
zip: 12345
},
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
}
};
const copy = JSON.parse(JSON.stringify(original));
console.log(copy);
/*
输出:
{
name: "Alice",
age: 30,
hobbies: ["reading", "gaming"],
address: { city: "Wonderland", zip: 12345 }
}
*/
copy.sayHello(); // TypeError: copy.sayHello is not a function
留意到 sayHello 方法在拷贝中被丢失,且对于 Date、RegExp 等范例也无法准确处理。
lodash 的 cloneDeep 详解
工作原理
lodash 的 cloneDeep 函数采用递归的方式,逐一复制对象的全部层级和属性,包罗复杂的数据范例和原型链上的属性。它还能处理循环引用,保持对象的完备性。
长处
[*]支持多种数据范例:
[*]可以准确处理对象、数组、函数、Date、RegExp、Map、Set 等复杂数据范例。
[*]保存 undefined、Symbol 等特别值(部门环境下大概会有限定)。
[*]处理循环引用:
[*]可以或许准确处理含有循环引用的对象,不会因递归导致堆栈溢出。
[*]性能优化:
[*]只管是第三方库,但在处理大型和复杂对象时,性能通常优于 JSON.parse(JSON.stringify())。
[*]广泛的社区支持与稳固性:
[*]lodash 颠末多年的开发和维护,拥有巨大的社区支持和丰富的功能模块。
缺点
[*]需要引入外部库:
[*]增长项目的依靠体积。
[*]需要额外的安装步调(但今世前端项目通常都会利用 lodash 或其他工具库)。
[*]大概存在性能瓶颈:
[*]对于极大型或极度复杂的数据布局,固然性能优越,但在某些特定场景下,仍大概比原生方法慢。
示例
import _ from 'lodash';
const original = {
name: "Bob",
age: 25,
hobbies: ["traveling", "sports"],
address: {
city: "Adventureland",
zip: 54321
},
createdAt: new Date(),
sayHello: function() {
console.log(`Hello, my name is ${this.name}`);
},
regexPattern: /abc/g
};
const copy = _.cloneDeep(original);
console.log(copy);
/*
输出:
{
name: "Bob",
age: 25,
hobbies: ["traveling", "sports"],
address: { city: "Adventureland", zip: 54321 },
createdAt: Date对象,
sayHello: function,
regexPattern: /abc/g
}
*/
copy.sayHello(); // 输出: Hello, my name is Bob
console.log(copy.createdAt instanceof Date); // true
console.log(copy.regexPattern instanceof RegExp); // true
可以看到,cloneDeep 可以或许准确复制函数、日期对象、正则表达式等复杂数据范例。
常见误区与留意事项
[*]JSON 方法无法处理函数和特别值:
[*]确保在不需要函数和特别值的环境下利用。
[*]JSON 方法会忽略 undefined 和 Symbol:
[*]如果对象属性包含 undefined 或 Symbol,会被忽略,导致信息丢失。
[*]JSON 方法不实用于循环引用:
[*]如果对象内部有循环引用,利用 JSON 方法 会导致堆栈溢堕落误。
[*]lodash cloneDeep 的依靠标题:
[*]如果项目自己已经利用了 lodash,那么利用 cloneDeep 是公道的选择。否则,引入整个 lodash 大概会增长打包体积。
[*]性能考虑:
[*]固然 lodash cloneDeep 功能强盛,但在性能敏感的场景下,确保举行基准测试,以确认其满足性能要求。
[*]不可变性与引用范例:
[*]即使举行了深拷贝,如果拷贝的属性是引用范例,而且在后续利用中未准确处理,依然大概出现引用标题。
总结
[*]JSON.parse(JSON.stringify()) 是一种轻便的深拷贝方法,但仅限于简单、可序列化的数据布局。它在性能上具有上风,但缺乏对复杂范例和特别场景的支持。
[*]lodash 的 cloneDeep 提供了更全面、更强盛的深拷贝功能,可以或许处理复杂的数据范例和循环引用,但需要额外的依靠和大概稍低的性能(视场景而定)。
选择发起
[*]简单对象:利用 JSON.parse(JSON.stringify()),代码更简便,性能更优。
[*]复杂对象:利用 lodash 的 cloneDeep,能处理复杂范例,提供更可靠的拷贝效果。
更多保举阅读内容
如安在 JavaScript 中优雅地移除对象字段?
轻松把握 Object.fromEntries:JavaScript中的实用本事
怎样将数组转换为对象(键为数组元素,值为 true)
JavaScript 嵌套数组扁平化的 5 种焦点方案与深度实践指南
玩转JavaScript排序黑邪术:Infinity的准确打开方式
解锁数组利用新维度:flatMap 深度分析与实战指南
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页:
[1]