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

yizhihongxing

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

在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日

相关文章

  • 极力推荐10个短小实用的JavaScript代码段

    接下来我来为大家讲解极力推荐10个短小实用的JavaScript代码段的攻略。 一、介绍 首先我们需要明确,这10个短小实用的JavaScript代码段主要是针对于前端开发者,能够帮助他们提高开发效率、优化用户体验、提供更好的交互和视觉效果。 这10个代码段分别是:1. 获取URL参数2. 倒计时3. 防抖4. 节流5. 数组去重6. 判断数组是否相等7. …

    JavaScript 2023年5月18日
    00
  • 《JavaScript DOM 编程艺术》读书笔记之JavaScript 简史

    下面是《JavaScript DOM 编程艺术》读书笔记之JavaScript 简史的详细攻略: 目录 简介 JavaScript 的诞生 JavaScript 的发展历程 JavaScript 的现状和未来 总结 简介 本篇读书笔记主要介绍了JavaScript的简史,该章节主要根据《JavaScript DOM 编程艺术》(第二版)第2章内容整理而来。 …

    JavaScript 2023年6月10日
    00
  • js判断传入时间和当前时间大小实例(超简单)

    下面是详细的讲解。 题目分析 题目要求我们编写一个 JavaScript 函数,能够判断传入的时间与当前时间的大小关系,即以当前时间为基准,判断传入时间是前面还是后面。 实现思路 我们可以使用 Date 对象获取当前时间和传入时间的时间戳,再进行比较即可。 时间戳是一个数字,表示某个时间点与 Unix 纪元时间点(1970 年 1 月 1 日 00:00:0…

    JavaScript 2023年5月27日
    00
  • 关于js中window.location.href,location.href,parent.location.href,top.location.href的用法与区别

    关于JS中window.location.href,location.href,parent.location.href,top.location.href的用法与区别 在JavaScript中,有多种获取当前窗口URL地址的方法,其中最常见的有window.location.href、location.href、parent.location.href和t…

    JavaScript 2023年6月11日
    00
  • 基于vue 动态菜单 刷新空白问题的解决

    那么让我们来详细讲解一下“基于Vue动态菜单刷新空白问题的解决”的完整攻略。 首先,我们需要了解静态菜单和动态菜单的区别。静态菜单是指在网站中写死的菜单,如果需要更改菜单内容或数量,就需要修改网站代码,并重新发布。而动态菜单是指在后台通过接口获取数据来动态生成菜单的方式,可以根据数据的变化而实现菜单的更新。 在Vue中,我们可以通过组件来实现动态菜单。常见的…

    JavaScript 2023年6月11日
    00
  • JavaScript中最容易混淆的作用域、提升、闭包知识详解(推荐)

    JavaScript中最容易混淆的作用域、提升、闭包知识详解 作用域 JavaScript采用词法作用域,即函数的作用域在函数定义时就已经确定了,不会随着函数调用的位置改变。因此,JavaScript中存在全局作用域和函数作用域。 全局作用域 全局作用域是指在代码的任何位置都可以访问的变量、函数和对象,它是在所有函数外部定义的作用域。 以下是一个示例,全局作…

    JavaScript 2023年5月28日
    00
  • javascript实现倒计时小案例

    下面是“JavaScript实现倒计时小案例”的完整攻略。 1. 准备工作 在编写倒计时小案例之前,需要掌握 JavaScript 基础语法,包括函数、变量、条件语句、循环语句等。同时,还需要了解日期对象 Date。以及能够基本运用 DOM 操作。 为了更好地构建简单的页面结构,可以使用 html 和 css。 2. 分析需求 在实现倒计时小案例之前,了解并…

    JavaScript 2023年5月27日
    00
  • JavaScript控制浏览器全屏显示简单示例

    关于“JavaScript控制浏览器全屏显示简单示例”的攻略,可以按照以下步骤进行: 1. HTML页面中添加按钮 首先,在HTML页面中添加一个按钮,以便在单击该按钮时全屏显示页面。可以使用以下代码: <button onclick="toggleFullScreen()">全屏显示</button> 其中onc…

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