JS实现数组深拷贝的方法分析

下面是一份详细的“JS实现数组深拷贝的方法分析”的攻略:

背景

在使用 JavaScript 中的数组时, 如果我们要将一个数组赋值给另一个变量, 只是简单地将数组变量赋给另一个变量,这样会导致两个变量指向同一个数组引用,即两个数组变量会指向同一个数组对象,如果只是数组的一些简单操作,这不会产生什么问题, 但如果涉及到多次修改某个数组,这时不停地修改一个数组会引用到其他变量之前时的状态,这样会影响程序运行结果。这时候,就需要对数组进行深拷贝。

方法

数组深拷贝有很多方法,比如使用 JSON 库深度复制、使用递归实现深度克隆、使用 ES6 的扩展符等等。下面将介绍其中两个方法:

方法一:JSON 库转换

const arr1 = [1, 2, { a: 3 }];
const arr2 = JSON.parse(JSON.stringify(arr1));

JSON 库中有两个方法:JSON.stringify()JSON.parse(),可以将任意复杂的东西转换成 JSON 字符串,再将这个 JSON 字符串解析成对象。在深拷贝数组中,我们可以利用 JSON 库的这两个方法:先把数组变成 JSON 字符串,再通过解析 JSON 字符串变成对象,从而达到深拷贝的目的。

但是,这种方法的缺陷是:它不能拷贝函数、正则、Date 等引用类型的值。

方法二:递归实现深度克隆

递归地从最简单的数据类型开始,每次返回时都进行一次克隆。遇到对象时,继续进行递归。

function deepClone(obj) {
  if (obj === null) {
    return null;
  }
  if (typeof obj !== "object") {
    return obj;
  }
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }
  const newObj = new obj.constructor();
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key]);
    }
  }
  return newObj;
}

const arr1 = [1, 2, { a: 3 }];
const arr2 = deepClone(arr1);

这种方法是通过递归实现深拷贝的。当拷贝的是基本类型时,直接返回该值,当是引用类型的时候,递归地拷贝该引用类型的值,并返回相应的克隆对象。这种方法比较完美地解决了 JSON 库方法的缺陷。

示例

下面两个示例将说明这两种方法分别是如何实现数组深拷贝的:

示例一:JSON 库转换

const arr1 = [1, 2, { a: 3 }, function () { console.log('hello') }];
const arr2 = JSON.parse(JSON.stringify(arr1));
arr2[2].a = 100;
console.log(arr1, arr2); // [1, 2, { a: 3 }, [Function]] [1, 2, { a: 100 }, null]

在这个示例中,我们把数组 arr1 赋值给 arr2 并使用 JSON 序列化和反序列化来完成深度复制。然后我们修改 arr2 的第三个元素,并输出 arr1 和 arr2。可以看到,虽然我们仅仅是修改了 arr2 的第三个元素,但 arr1 也跟着变了,即两个数组的第三个元素是不同的。

示例二:递归实现深度克隆

function deepClone(obj) {
  if (obj === null) {
    return null;
  }
  if (typeof obj !== "object") {
    return obj;
  }
  if (obj instanceof Date) {
    return new Date(obj.getTime());
  }
  if (obj instanceof RegExp) {
    return new RegExp(obj);
  }
  const newObj = new obj.constructor();
  for (const key in obj) {
    if (obj.hasOwnProperty(key)) {
      newObj[key] = deepClone(obj[key]);
    }
  }
  return newObj;
}

const arr1 = [1, 2, { a: 3 }, function () { console.log('hello') }];
const arr2 = deepClone(arr1);
arr2[2].a = 100;
console.log(arr1, arr2); // [1, 2, { a: 3 }, [Function]] [1, 2, { a: 100 }, [Function]]

在这个示例中,我们使用递归方式来实现数组的深拷贝,同时也打印出 arr1 和 arr2 以验证两个数组对象的不同。由于我们使用了递归方式实现深拷贝,因此即使修改了 arr2 的第三个元素,arr1 也不会受到影响,两个数组对象是相互独立的。

结论

通过上面的两个示例,我们可以明确“JS实现数组深拷贝的方法分析”的攻略。

总的来说,利用 JSON 库的方法实现数组的深拷贝是最简单的方法,只需一些简单的代码即可。但是它有明显的缺陷,即无法深拷贝 Date、正则、函数等引用类型的值。

递归方式实现深拷贝是比较完美的解决方案,但需要考虑的细节会比较多,比如如何判断一个值是不是基本类型。如果拷贝的对象过于复杂,则递归方法的效率也比较低。

在实际应用中,需要根据具体的业务需求和性能要求选择不同的实现方法。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:JS实现数组深拷贝的方法分析 - Python技术站

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

相关文章

  • 微信小程序模板(template)使用详解

    微信小程序模板(template)使用详解 什么是微信小程序模板(template) 微信小程序模板是一种快速开发小程序的方式,类似于其他web开发中的样板(boilerplate)或模板(template)等概念。使用小程序模板,可以减少从零开始开发的代码量,加快小程序开发的速度。 如何使用微信小程序模板 在小程序开发工具中,选择“新建小程序”或“创建项目…

    JavaScript 2023年6月11日
    00
  • 利用TypeScript编写贪吃蛇游戏

    下面是”利用TypeScript编写贪吃蛇游戏”的完整攻略: 准备工作 在开始编写贪吃蛇游戏之前,需要安装Node.js和npm(Node.js自带npm)。随后可以使用以下命令安装TypeScript: npm install -g typescript 创建项目 创建一个新目录并进入,执行以下命令: npm init -y 上述命令将创建package.…

    JavaScript 2023年6月11日
    00
  • JavaScript常用工具函数大全

    JavaScript常用工具函数大全 本文将收集整理一些常用的 JavaScript 工具函数,旨在帮助开发者在日常工作中更加高效地编写代码。 1. 数组相关函数 1.1 isArray() 判断一个值是否是数组。 function isArray(value) { return Array.isArray(value); } 示例: isArray([])…

    JavaScript 2023年5月27日
    00
  • 解析dom中的children对象数组元素firstChild,lastChild的使用

    当我们使用JavaScript解析DOM时,经常需要访问一个元素的子节点。在DOM树种,每个元素节点都有一个名为children的属性,它引用了该元素的所有子节点。children属性返回一个子节点的NodeList对象,可以通过它访问节点列表。在这个NodeList对象中,每个子节点都有一个firstChild和一个lastChild属性,分别是该元素的第…

    JavaScript 2023年6月10日
    00
  • JS的Form表单转JSON格式的操作代码

    JS的Form表单转JSON格式的操作代码可以通过以下步骤实现: 获取表单元素 使用document.querySelector()方法获取到表单元素对象。例如: const form = document.querySelector(‘#myForm’); 遍历表单元素 使用forEach()方法遍历表单元素的所有表单控件,并将其转换为JSON格式。例如:…

    JavaScript 2023年5月27日
    00
  • javascript中的with语句学习笔记及用法

    JavaScript 中的 with 语句学习笔记及用法 with 语句是 JavaScript 中的一个语法结构,可以方便地访问同一个对象中的多个属性或方法,从而简化代码。但是,使用 with 语句会在某些情况下引发一些不容易被发现的“错误”,所以在使用时需要注意。 语法 with 语句的基本语法如下: with (object) { // code bl…

    JavaScript 2023年6月10日
    00
  • url参数中有+、空格、=、%、&、#等特殊符号的问题解决

    针对url参数中包含特殊符号导致的问题,可以采取以下措施进行解决: 一、使用URL编码 URL编码是将URL中的非英文字母和数字都用百分号(%)加两个16进制数字表示的方式进行转换,以确保它们能够正常传输和处理。常用的URL编码方法是使用Javascript内置对象encodeURIComponent()函数。例如: https://www.example.…

    JavaScript 2023年5月19日
    00
  • js中substring和substr的详细介绍与用法

    JS中substring和substr的详细介绍与用法 概述 JavaScript中的substring()和substr()函数均可用于截取一个字符串的一部分,但它们的使用方式略有不同。 substring() substring()函数用于截取字符串的一部分,并返回一个新的字符串。它接受两个参数,第一个参数是起始位置,第二个参数是结束位置(不含)。如果没…

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