javascript进阶篇深拷贝实现的四种方式

yizhihongxing

Javascript进阶篇:深拷贝实现的四种方式

在Javascript中,数据类型可以分为原始类型和引用类型。其中,原始类型在赋值、作为函数参数、返回值传递等情况下,直接进行值的传递。而引用类型则是传递引用地址。这样一来,在同一个作用域下、赋值、作为函数参数、返回值传递等情况下,多个变量可能会指向同一引用地址的内存空间,导致某些问题。为了避免这种问题,我们需要对引用类型进行深拷贝。

本文将介绍四种Javascript实现深拷贝的方式:

方式一:JSON.parse(JSON.stringify(obj))

利用JSON.stringify可以把JSON对象转换为字符串,JSON.parse方法可以把字符串转换为对象的特性,可以达到深拷贝的效果。

let obj = {a: 1, b: {c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false

但也有需要注意的点,比如:

  • undefined无法被序列化,所以在原对象中该属性会被忽略;
  • NaN、Infinity和-Infinity会被转化为null;
  • Date日期对象也无法被序列化(Javascript中日期对象都有一个toString方法,因此JSON.stringify调用Date对象时会把日期转换成字符串);
  • 对象中函数属性会被忽略掉;
  • 对象中RegExp、Error对象等特殊对象无法被序列化;
  • 如果obj对象中存在循环引用的情况也无法正确实现深拷贝。

方式二:递归遍历对象拷贝

递归遍历对象,对于每一个属性进行递归操作,从而实现深拷贝。

function deepClone(obj) {
  let newObj = obj instanceof Array ? [] : {};
  for(let i in obj){
    if (typeof obj[i] === 'object') {
      newObj[i] = deepClone(obj[i]);
    } else {
      newObj[i] = obj[i];
    }
  }
  return newObj;
}

let obj = {a: 1, b: {c: 2}};
let newObj = deepClone(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false

需要注意的是,递归深拷贝也需要注意循环引用的问题。

方式三:利用Object.assign

Object.assign方法可以使用多个源对象中的属性和方法拷贝到一个目标对象中去。利用这个特性,我们也可以实现深拷贝。

function deepClone(obj) {
  let newObj = obj instanceof Array ? [] : {};
  if (typeof obj !== 'object') {
    return obj;
  }
  for(let i in obj){
    if (typeof obj[i] === 'object') {
      newObj[i] = deepClone(obj[i]);
    } else {
      newObj[i] = obj[i];
    }
  }
  let temp = Object.assign({}, obj, newObj);
  return temp;
}

let obj = {a: 1, b: {c: 2}};
let newObj = deepClone(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false

与上一个方法类似,也需要注意循环引用的问题。

方式四:使用第三方库

使用第三方库中的深拷贝方法,如lodash中的_.cloneDeep方法。这个方法可以深度克隆一个对象,包括原型链。

let obj = {a: 1, b: {c: 2}};
let newObj = _.cloneDeep(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false

需要注意的是,使用第三方库虽然方便,但是也会增加代码依赖和体积。

总结

以上四种Javascript实现深拷贝的方式,各有利弊。在具体项目中,我们需要根据实际情况进行选择。需要注意的是,在实现深拷贝时,需要考虑到循环引用、特殊对象等特殊情况,以避免影响程序的正常运行。

两条示例:

  • 示例一:使用JSON.parse(JSON.stringify(obj))进行深拷贝
let obj = {a: 1, b: {c: 2}};
let newObj = JSON.parse(JSON.stringify(obj));
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false
  • 示例二:使用第三方库lodash的深拷贝方式
let obj = {a: 1, b: {c: 2}};
let newObj = _.cloneDeep(obj);
console.log(obj === newObj); // false
console.log(obj.b === newObj.b); // false

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:javascript进阶篇深拷贝实现的四种方式 - Python技术站

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

相关文章

  • 如何使用jQuery在父节点的偶数个子节点中应用CSS

    在jQuery中,可以使用nth-child()选择器来选择父节点的偶数个子节点,并使用css()方法来应用CSS。以下是如何使用jQuery在父节点的偶数个子节点中用CSS的完整攻略: 步骤一:创建HTML结构 首先需要创建一个包含子节点的HTML结构。以下是一个示例: <!DOCTYPE html> <html> <head…

    jquery 2023年5月9日
    00
  • jQWidgets jqxWindow disable()方法

    jQWidgets是一个UI组件库,其中的jqxWindow组件提供了多种窗口显示效果。其中disable()是jqxWindow组件提供的方法之一,可以用于禁用窗口,防止用户对窗口进行操作。 使用disable()方法之前,需要先创建一个jqxWindow对象,可以通过如下代码创建: $("#window").jqxWindow({ /…

    jquery 2023年5月12日
    00
  • jQWidgets jqxGrid showgroupmenuitems属性

    jQWidgets jqxGrid showgroupmenuitems属性详解 jQWidgets jqxGrid 是一种表格控件,用于在 Web 应用程序中创建表格。showgroupmenuitems是 jqxGrid 控件的一个属性,用于指定是否显示分组菜单项。本文将详细讲解 showgroupmenuitems的使用方法,并提供两个示例说明。 属性…

    jquery 2023年5月10日
    00
  • jQWidgets jqxScheduler scrollBarSize属性

    当在 jqxScheduler 控件上启用滚动条时,可以使用 scrollBarSize 属性来配置滚动条的宽度和高度。该属性通常用于定制滚动条的大小,以适应不同的界面设计。 下面是详细的攻略,包括该属性的用途、值以及代码示例: 什么是scrollBarSize属性 scrollBarSize 属性是 jqxScheduler 控件的一个配置项,可以用来设置…

    jquery 2023年5月11日
    00
  • webpack 最佳配置指北(推荐)

    下面是关于“webpack最佳配置指北(推荐)”的详细攻略: 一、什么是Webpack? Webpack是一个打包工具,它可以将多个模块打包成一个文件,以减少网络请求的次数,提高页面加载速度。Webpack的配置相对比较复杂,但是只要掌握了它的一些基本概念和配置方法,就可以轻松地优化你的项目。 二、Webpack配置的基本概念 Webpack的配置基本上都在…

    jquery 2023年5月27日
    00
  • jQWidgets jqxBarcode backgroundColor属性

    jQWidgets jqxBarcode backgroundColor属性 jQWidgets是一个基于jQuery的UI组件库,提供了丰富的UI组件和工具,包括表格、图表、表单、日历、菜单等。其中,jqxBarcode是jQWidgets中的一个条形码组件,可以用于生成各种类型的条形码。本文将详细介绍jqxBarcode的backgroundColor属…

    jquery 2023年5月9日
    00
  • jQWidgets jqxTree dragStart事件

    当用户开始拖动 jQWidgets jqxTree 组件中的节点时,dragStart 事件将被触发。以下是 jQWidgets jqxTree dragStart 事件的完整攻略,包括语法、参数、示例等内容。 jQWidgets jqxTree dragStart事件 dragStart 事件在用户开始拖动 jQWidgets jqxTree 组件中的节点…

    jquery 2023年5月11日
    00
  • jquery 选择器部分整理

    当然,让我为你详细讲解一下 “jQuery选择器部分整理” 的攻略。 什么是jQuery选择器? 在jQuery中,选择器用于选择指定元素,可以根据元素的ID、类、属性等进行选择。这使得在文档中寻找和改变元素成为了一件非常容易的事情。 选择器的语法 选择器通常以 $ 符号开始,后面跟着一个包含在引号中的选择器表达式。例如: $(‘#myId’); // 通过…

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