带你搞懂js的深拷贝

带你搞懂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日

相关文章

  • js 数组随机字符串(广告不重复)

    首先需要了解“数组”和“随机数”的概念。 数组 数组是一组按照顺序排列的值的集合。值可以是任何数据类型,如字符串、数字、对象等。在 JavaScript 中,数组用方括号表示 [],并用逗号分隔其中的值。 随机数 随机数是指没有规律可循的随机输出的数字或序列。在 JavaScript 中,可以通过 Math.random() 方法生成一个介于 0 (包括)和…

    JavaScript 2023年5月28日
    00
  • 理解JavaScript事件对象

    理解JavaScript事件对象在事件处理中是非常重要的。在JavaScript中,事件对象(Event Object)是事件处理函数中的第一个参数。当特定事件被触发时,浏览器会自动创建事件对象(Event Object)。开发者可以使用该对象在事件处理函数中访问事件的详细信息,例如鼠标位置,按键,以及事件类型等。 JavaScript事件对象的属性 事件对…

    JavaScript 2023年5月27日
    00
  • 极力推荐10个短小实用的JavaScript代码段

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

    JavaScript 2023年5月18日
    00
  • JavaScript实现身份证验证代码

    下面我将详细讲解如何使用JavaScript实现身份证验证代码的完整攻略。 步骤一:获取用户输入的身份证号码 首先,需要在页面上获取用户输入的身份证号码。可以在HTML文件中添加一个文本框输入框,让用户输入身份证号码,在通过JavaScript获取该文本框中的值。 HTML代码如下: <label for="idcard">请…

    JavaScript 2023年6月10日
    00
  • JS JSON对象转为字符串的简单实现方法

    一、背景概述 JSON对象是JavaScript中处理数据的重要方式之一。当需要将JSON对象转换为字符串时,我们通常要使用JSON.stringify()方法来实现。本文将详细说明如何将JSON对象转换为字符串,以便网站作者们更好地理解和应用。 二、JSON.stringify()方法介绍 JSON.stringify()是JavaScript的一个标准方…

    JavaScript 2023年5月27日
    00
  • JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】

    下面就给大家讲解一下“JS实现集合的交集、补集、差集、去重运算示例【ES5与ES6写法】”的完整攻略。 1. 集合的定义和常用运算 1.1 集合的定义 集合(Set)是一种专门存储不重复值的数据结构。它可以存储各种类型的原始值和对象引用。与数组不同的是,集合没有顺序概念,因此不能通过索引访问元素。集合中的数据也没有重复,每个元素的位置都是唯一的。 1.2 集…

    JavaScript 2023年5月28日
    00
  • 在react中使用mockjs的方法你知道吗

    当我们需要模拟一个后端API接口,来测试前端代码的时候,可以使用mockjs这个库进行模拟数据。下面是在React中使用mockjs的方法: 1. 安装mockjs npm install mockjs –save-dev 2. 创建mock数据 我们可以在src目录下新建一个mock目录,然后在这个目录下再新建一个data.js文件。在这个文件中,就可以…

    JavaScript 2023年6月10日
    00
  • 使用 JScript 创建 .exe 或 .dll 文件的方法

    以下是使用 JScript 创建 .exe 或 .dll 文件的方法的完整攻略。 方案1:使用 JScript.NET 创建 .dll 文件 步骤1:打开 Visual Studio 并创建新项目 打开 Visual Studio。在菜单栏上选择“文件” -> “新建” -> “项目”。 在“新建项目”对话框中,选择“Visual J#” -&g…

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