前端踩坑之数组拷贝

栏目: 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)会导致调用栈溢出
  • 通过闭包作用域来实现私有成员的这类对象不能真正的被拷贝。

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

查看所有标签

猜你喜欢:

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

Windows高级调试

Windows高级调试

Mario Hewardt、Daniel Pravat / 聂雪军 / 机械工业出版社 / 2009-5 / 79.00元

本书主要讲解Windows高级调试思想和工具,并涉及一些高级调试主题。本书内容主要包括:工具简介、调试器简介、调试器揭密、符号文件与源文件的管理、栈内存破坏、堆内存破坏、安全、进程间通信、资源泄漏、同步、编写定制的调试扩展、64位调试、事后调试、Windows Vista基础以及应用程序验证器的测试设置等。本书内容详实、条理清楚。 本书适合Windows开发人员、Windows测试人员和Windo......一起来看看 《Windows高级调试》 这本书的介绍吧!

图片转BASE64编码
图片转BASE64编码

在线图片转Base64编码工具

UNIX 时间戳转换
UNIX 时间戳转换

UNIX 时间戳转换

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具