带你搞懂js的深拷贝

yizhihongxing

带你搞懂js的深拷贝

在JavaScript中,拷贝是一项非常重要的任务,因为在JavaScript中,赋值操作并不是简单的复制一个变量的值到另一个变量,而是复制该变量所持有的引用地址,这意味着如果你直接将一个变量赋值给另一个变量,那么两者将共享同一份数据,即数据的修改将会同步。因此,当你需要对数据进行操作和修改时,深拷贝是至关重要的。

深拷贝的实现

实现一个深拷贝的算法可以分为两个步骤:

  1. 将对象进行递归拷贝或者循环拷贝
  2. 将拷贝后的对象返回

递归拷贝

某些情况下,递归拷贝可以比循环拷贝更简单和可读性更好。一个基本的递归拷贝的实现如下:

function deepClone(obj) {
  if (obj === null) return null; // 判断null

  if (typeof obj !== 'object') return obj; // 判断基本类型,直接返回

  if (obj.constructor === Date) return new Date(obj); // 判断Date类型
  if (obj.constructor === RegExp) return new RegExp(obj); // 判断RegExp类型

  const newObj = new obj.constructor(); // 通过构造函数创建对象

  for (let key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key]); //递归拷贝
    }
  }

  return newObj; // 返回新对象
}

循环拷贝

循环拷贝是另一种实现深拷贝的方式,使用循环拷贝的好处是可以避免递归深度过深导致的栈溢出问题。一个基本的循环拷贝的实现如下:

function deepClone(obj) {
  const stack = [];
  const newObj = new obj.constructor();

  stack.push({
    parent: newObj,
    key: undefined,
    data: obj
  });

  while (stack.length !== 0) {
    const node = stack.pop();
    const { parent, key, data } = node;

    if (typeof data === 'object') {
      const clone = new data.constructor();
      Object.defineProperty(parent, key, {
        value: clone,
        writable: true,
        enumerable: false,
        configurable: true
      });
      for (let i in data) {
        stack.push({
          parent: clone,
          key: i,
          data: data[i]
        });
      }
    } else {
      Object.defineProperty(parent, key, {
        value: data,
        writable: true,
        enumerable: false,
        configurable: true
      });
    }
  }

  return newObj;
}

在这个实现中,我们使用了一个栈(stack)来模拟递归过程。栈中每个元素代表了原始对象的一个属性,并且保存了当前拷贝对象上一级的父级、当前属性的键以及该属性所指向的原始对象。

示例说明

下面给短示两个简单的例子,帮助理解深拷贝过程。

示例 1:

const a = { name: 'Tom', birthday: new Date() };
const b = deepClone(a);
console.log(b); // { name: 'Tom', birthday: Date }

a.birthday.setFullYear(2000);
console.log(a.birthday); // 2000-xx-xx
console.log(b.birthday); // 当前日期

在这个例子中,我们定义了一个含有Date类型属性的对象,在将该对象深拷贝后,修改原始数据的Date类型属性,不会影响拷贝后的数据。

示例 2:

const a = { name: 'Tom', friends: ['Jerry', 'Bob'] };
const b = deepClone(a);
console.log(b); // { name: 'Tom', friends: ['Jerry', 'Bob'] }

a.friends.push('Kate');
console.log(a.friend); // ['Jerry', 'Bob', 'Kate']
console.log(b.friend); // ['Jerry', 'Bob']

在这个例子中,我们定义了一个含有数组属性的对象,在将该对象深拷贝后,修改原始数据的数组属性,不会影响拷贝后的数据。这是因为深拷贝过程中,数组被拷贝为一个新的数组,拥有自己的内存空间,不会受到原始数据的影响。

结语

关于JavaScript的深拷贝还有很多细节和实现方式,这里只提供了一个基本的模板和两个简单的示例。希望可以帮助你更好地理解深拷贝的概念和实现。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:带你搞懂js的深拷贝 - Python技术站

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

相关文章

  • 常用的9个JavaScript图表库详解

    常用的9个JavaScript图表库详解 1. Chart.js Chart.js 是一个使用 HTML5 canvas 元素创建图表的 JavaScript 库。它可以绘制多种类型的图表,例如线性图、柱状图、饼图等等。 Chart.js 具有良好的文档和易于使用的 API。它适合初学者和有经验的开发者。 以下是一个简单的例子: <canvas id=…

    JavaScript 2023年5月27日
    00
  • JavaScript常用正则验证函数实例小结【年龄,数字,Email,手机,URL,日期等】

    这个问题需要比较详细的回答,以下是完整攻略: 什么是正则表达式? 正则表达式,又称正规表示式、正规表示法、规则表达式、常规表示法(英语:Regular Expression,在代码中常简写为 regex、regexp 或 RE),是计算机科学的一个概念。正则表达式通常缩写为 regex,在某些情况下也被称为模式匹配,是一种用来描述、匹配一系列符合某个语法规则…

    JavaScript 2023年5月28日
    00
  • JSP页面跳转方法大全

    下面我详细讲解一下“JSP页面跳转方法大全”的完整攻略。 标准的JSP页面跳转方法 1.使用response.sendRedirect()方法 response.sendRedirect()方法可以用来实现重定向,具体实现就是在response对象中设置一个响应头的Location来指定新的请求路径,例如: response.sendRedirect(&qu…

    JavaScript 2023年6月11日
    00
  • 纯编码实现微信小程序弹幕效果(非视频底)

    纯编码实现微信小程序弹幕效果(非视频底)的完整攻略分为以下几个步骤: 步骤一:创建一个基础的弹幕组件 首先,我们需要在小程序页面中创建一个基础的弹幕组件,实现弹幕的基本功能。 整体的实现思路如下: 使用 CSS 中的 position、left、top 属性实现弹幕的位置控制。 使用 Animation API 中的 translateX、translate…

    JavaScript 2023年5月19日
    00
  • js获取TreeView控件选中节点的Text和Value值的方法

    获取TreeView控件选中节点的Text和Value值,可以使用JavaScript来实现。具体方法如下: 方法一:利用ASP.NET自身提供的控件属性 ASP.NET的TreeView控件提供了一个SelectedNode属性,可以获取选中的节点。在此基础上,我们可以通过SelectedNode的Text和Value属性获取选中节点的文本和值。 // 获…

    JavaScript 2023年6月10日
    00
  • javascript格式化指定日期对象的方法

    要格式化指定日期对象,我们可以使用JavaScript的内置Date对象中的方法。 1、使用toLocaleString()方法 Date对象内置方法toLocaleString()能够格式化日、月、年、小时、分钟、秒和时间格式。例如: const date = new Date(); const formattedDate = date.toLocaleS…

    JavaScript 2023年5月27日
    00
  • JavaScript实现同时调用多个函数的方法

    为了实现同时调用多个函数,有两种方法可以选择:串行和并行。串行指的是按照指定的顺序依次执行函数,而并行指的是同时执行所有函数,不关心它们的顺序。 串行调用函数的方法 方法一:Promise 利用 ES6 的 Promise 实现,可以方便地实现多个函数的串行调用。 Promise 对象的主要作用是为处理异步操作提供一个统一的接口,其中包含三个状态:进行中(p…

    JavaScript 2023年5月27日
    00
  • ASP.NET笔记之 ListView 与 DropDownList的使用

    ASP.NET笔记之 ListView 与 DropDownList的使用 介绍 在ASP.NET中,ListView和DropDownList都是常用的控件之一,ListView可以显示多行数据并提供样式控制,DropDownList则是提供了下拉列表的选择功能。本文将详细讲解ListView和DropDownList的使用,包括基本概念、属性设置和样式控…

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