前端踩坑之数组拷贝

栏目: JavaScript · 发布时间: 5年前

内容简介:众所周知,在 JavaScript 中对象之间的赋值,只是拷贝对象的引用,也就是浅拷贝,不是真正意义上的拷贝,两个对象之间还会相互影响。然而,我一直忽略了一个问题,数组之间的拷贝会不会也有同样的问题呢?果不其然,当我再次用常用的 array.concat() 方法拷贝数组时,踩到坑了。当我改变一个数组里面对象属性的时候,另一个数组里的对象也跟着改变了。。。这种拷贝方法是这几种方法产生的效果是一样的。

众所周知,在 JavaScript 中对象之间的赋值,只是拷贝对象的引用,也就是浅拷贝,不是真正意义上的拷贝,两个对象之间还会相互影响。然而,我一直忽略了一个问题,数组之间的拷贝会不会也有同样的问题呢?果不其然,当我再次用常用的 array.concat() 方法拷贝数组时,踩到坑了。当我改变一个数组里面对象属性的时候,另一个数组里的对象也跟着改变了。。。

数组的拷贝方法有很多,按结果来看就是浅拷贝和深拷贝两种。

一、直接赋值

let arr2 = arr1;
复制代码

这种拷贝方法是 浅拷贝 ,数组arr1和数组arr2共用同一内存,其中一个数组改变,另一个数组也会跟着改变。

二、使用 slice(),concat(),assign() 方法

let arr2 = arr1.slice(0);
let arr3 = [].concat(arr1);
let arr4 = Object.assign({} , arr1);
复制代码

这几种方法产生的效果是一样的。

  • 若原数组中 不存在 引用类型,修改新数组, 不会 影响到原数组的值。
  • 若原数组中 存在 引用类型,修改新数组, 影响到原数组的值

原因是这样拷贝数组中 非引用类型 的值属于 拷贝, 引入类型 的值属于 拷贝。

三、深拷贝方法

1. JSON复制法

let arr2 = JSON.parse(JSON.stringify(arr1));
复制代码

但是这种方式有一定的局限性,就是数组必须遵从JSON的格式,当遇到层级较深,且序列化数组不完全符合JSON格式时,使用JSON的方式进行深拷贝就会出现问题。

所有函数及原型成员都会被有意忽略,不体现在结果中。此外,值为 undefined 的任何属性也都会被跳过。结果中最终都是值为有效 JSON 数据类型的实例属性。

2. 使用递归

function deepClone(source) {
  // 递归终止条件
  if (!source || typeof source !== 'object') {
    return source;
  }
  var targetObj = source.constructor === Array ? [] : {};
  for (var key in source) {
    if (Object.prototype.hasOwnProperty.call(source, key) {
      if (source[key] && typeof source[key] === 'object') {
        targetObj[key] = deepClone(source[key]);
      } else {
        targetObj[key] = source[key];
      }
    }
  }
  return targetObj;
}

复制代码

对于 Function 类型,这里是直接复制的,任然是共享一个内存地址。因为函数更多的是完成某些功能,对函数的更改可能就是直接重新赋值,一般情况下不考虑深拷贝。 上面的深拷贝只是比较简单的实现,没有考虑很复杂的情况,比如:

  • 其他引用类型:Function,Date,RegExp 的拷贝
  • 对象中存在循环引用(Circular references)会导致调用栈溢出
  • 通过闭包作用域来实现私有成员的这类对象不能真正的被拷贝。

以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

The Pragmatic Programmer

The Pragmatic Programmer

Andrew Hunt、David Thomas / Addison-Wesley Professional / 1999-10-30 / USD 49.99

本书直击编程陈地,穿过了软件开发中日益增长的规范和技术藩篱,对核心过程进行了审视――即根据需求,创建用户乐于接受的、可工作和易维护的代码。本书包含的内容从个人责任到职业发展,直至保持代码灵活和易于改编重用的架构技术。从本书中将学到防止软件变质、消除复制知识的陷阱、编写灵活、动态和易适应的代码、避免出现相同的设计、用契约、断言和异常对代码进行防护等内容。一起来看看 《The Pragmatic Programmer》 这本书的介绍吧!

HTML 压缩/解压工具
HTML 压缩/解压工具

在线压缩/解压 HTML 代码

XML 在线格式化
XML 在线格式化

在线 XML 格式化压缩工具

HEX CMYK 转换工具
HEX CMYK 转换工具

HEX CMYK 互转工具