前端使用JSON.stringify实现深拷贝的巨坑详解

首先,需要明确深拷贝和浅拷贝的概念。

在JavaScript中,对象的赋值有两种方式:深拷贝和浅拷贝。浅拷贝只是将对象的引用复制给了新的变量,而深拷贝则是递归地复制对象及所有嵌套的子对象。

JSON.stringify可以将一个JavaScript对象序列化成一个JSON字符串,而JSON.parse则可以将一个JSON字符串反序列化成一个JavaScript对象。所以,看起来使用JSON.stringify和JSON.parse就可以实现深拷贝了,但是实际情况并非如此。

下面是使用JSON.stringify实现深拷贝的错误示例:

let obj = { a: 1, b: { c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c = 3;
console.log(newObj.b.c); // 输出结果为2,而不是期望的3

上面的代码中,obj对象中有一个嵌套的对象{ c: 2 },将obj对象通过JSON.stringify序列化成JSON字符串后,再通过JSON.parse将其反序列化成一个新的对象newObj。此时,obj对象中嵌套对象的值被修改后,newObj对象中的值并没有跟着改变。但是,如果嵌套的子对象{ c: 2 }中也含有嵌套的子对象,像这样:

let obj = { a: 1, b: { c: { d: 2}}};
let newObj = JSON.parse(JSON.stringify(obj));
obj.b.c.d = 3;
console.log(newObj.b.c.d); // 输出结果是3,而不是期望的2

此时,newObj对象中的值跟着被修改。这是因为,在JSON.stringify序列化时,嵌套的子对象并不会被递归地复制,而是仍然继续使用原来的引用,因为JSON.stringify无法序列化函数和对象的属性中具有undefined的值。这就会导致嵌套的子对象在后续的修改中也会被更改。因此,在使用JSON.stringify实现深拷贝时,需要特别注意这个坑。

下面是使用递归实现深拷贝的示例:

function deepClone(obj) {
  if (obj === null || typeof obj !== 'object') {
    return obj;
  }
  var newobj = {}
  for (var key in obj) {
    newobj[key] = deepClone(obj[key]);
  }
  return newobj;
}

let obj = { a: 1, b: { c: { d: 2}}};
let newObj = deepClone(obj);
obj.b.c.d = 3;
console.log(newObj.b.c.d); // 输出结果为2,不会被后续修改影响到

上面的代码中,我们使用递归的方式实现深拷贝,确保了嵌套的子对象也得到了复制,不会因为后续的修改而发生变化。

总之,如果需要实现对象的深拷贝,使用JSON.stringify并不是可靠的方法,而是需要使用递归等其他方式来确保嵌套的子对象也被复制,避免出现意外的错误。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:前端使用JSON.stringify实现深拷贝的巨坑详解 - Python技术站

(0)
上一篇 2023年5月27日
下一篇 2023年5月27日

相关文章

  • JavaScript面向对象的两种书写方法以及差别

    JavaScript是一种面向对象的编程语言,在JavaScript中,我们可以使用两种方法来定义对象和类。这两种方法分别是原型(Prototype)和类(Class)。它们有着不同的语法,但都有着相同的功能,即定义和创建对象。 原型(Prototype)方法 原型(Prototype)是JavaScript中的一个重要概念,它给JavaScript提供了一…

    JavaScript 2023年5月27日
    00
  • JS中实现浅拷贝和深拷贝的代码详解

    浅拷贝和深拷贝是JavaScript中常用的两种复制对象的方法,两者的差别在于复制后对象所指向的地址是否相同。如果新生成的对象与原对象的内存地址相同,我们就称为浅拷贝;如果新生成的对象与原对象的内存地址不同,那么就称为深拷贝。 浅拷贝的实现 浅拷贝可以通过Object.assign()方法、扩展操作符或者遍历实现: Object.assign()方法实现浅拷…

    JavaScript 2023年6月10日
    00
  • js中Array.forEach跳出循环的方法实例

    在JavaScript中,使用Array.forEach()方法可以遍历数组,并对每一个元素执行相应的操作。在实际开发中,有时候需要在某些条件下跳出forEach循环,本文将详细讲解该如何在forEach循环中跳出循环。 方法一:使用try-catch语句 在forEach中使用try-catch语句,当需要跳出循环时,通过throw new Error()…

    JavaScript 2023年5月27日
    00
  • jquery的$getjson调用并获取远程的JSON字符串问题

    当我们希望从远程的JSON文件中获取数据时,可以使用jQuery库中的getJSON函数。下面,我将为大家详细讲解“jQuery的getJSON调用并获取远程的JSON字符串问题”的完整攻略,包括使用方法和示例说明。 使用方法 getJSON函数是jQuery库中的一个方法,其作用是从服务器获取JSON格式数据,其基本语法格式如下所示: $.getJSON(…

    JavaScript 2023年5月27日
    00
  • JavaScript调试常见报错及原因分析

    JavaScript调试常见报错及原因分析 在JavaScript开发过程中,经常会遇到一些常见的报错,这些报错会影响到程序的运行。本文将介绍JavaScript调试常见报错及其原因分析的攻略。 报错类型 SyntaxError SyntaxError会在代码无法解析的情况下被抛出,例如: let a = 5 if (a == 5) { console.lo…

    JavaScript 2023年6月11日
    00
  • JavaScript中字符串的常用方法总结

    下面是完整的“JavaScript中字符串的常用方法总结”的攻略。 字符串长度 length 方法可以用来获取一个字符串的长度,即包含的字符数量。 const str = "Hello, World!"; console.log(str.length); // 13 字符串索引 字符串中的每一个字符都可以通过一个索引来访问,这个索引从 0…

    JavaScript 2023年5月18日
    00
  • 浅谈javascript对象模型和function对象

    我将根据您的要求,为您详细讲解Javascript对象模型和function对象的相关知识。 Javascript对象模型 Javascript对象模型(Object Model)是一种按照一定规则组织和管理代码的方式。在Javascript中,所有的事物都是对象(Object),包括数组、函数等。对象是通过“对象字面量”(Literal)创建的,也可以通过…

    JavaScript 2023年5月27日
    00
  • 关于JS字符串函数String.replace()

    那么让我们开始关于JS字符串函数String.replace()的详细讲解。 String.replace()概述 String.replace(searchValue, replaceValue)是用于将字符串中匹配某个模式的子串,替换成另一个指定的字符串。这个函数可以接受两个参数: searchValue:需要被替换的子串,它可以是一个字符串或者一个正则…

    JavaScript 2023年5月28日
    00
合作推广
合作推广
分享本页
返回顶部