javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法

前言

在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝。如下图演示: 
 
如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并不是我们所需要的结果。 
因此,数组以及对象的深拷贝就是javascript的一个基本功了。

数组的深拷贝

条条大道通罗马,实现数组的深拷贝,是有好几种方法的。举例如下:

for 循环实现数组的深拷贝

for循环是非常好用的。如果不知道高级方法,通过for循环能够完成我们大多数的需求。

var arr = [1,2,3,4,5]
var arr2 = copyArr(arr)
function copyArr(arr) {
let res = []
for (let i = 0; i < arr.length; i++) {
res.push(arr[i])
}
return res
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

如上,通过对数组的for循环,即可实现对数组的深拷贝了。

slice 方法实现数组的深拷贝

这个代码实现非常简单。原理也比较好理解,他是将原数组中抽离部分出来形成一个新数组。我们只要设置为抽离全部,即可完成数组的深拷贝。代码如下:

var arr = [1,2,3,4,5]
var arr2 = arr.slice(0)
arr[2] = 5
console.log(arr)
console.log(arr2)
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果如下: 
 
更多 slice 内容请访问 w3school JavaScript slice 方法

concat 方法实现数组的深拷贝

这个代码也非常简单,原理更加粗暴。它是用于连接多个数组组成一个新的数组的方法。那么,我们只要连接它自己,即可完成数组的深拷贝。代码如下:

var arr = [1,2,3,4,5]
var arr2 = arr.concat()
arr[2] = 5
console.log(arr)
console.log(arr2)
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果如下: 
 
更多 concat 内容请访问 w3school JavaScript concat 方法

2017年10月31日补充:ES6扩展运算符实现数组的深拷贝

OK,以上之前讲的方法全部过时了,用下面的方法实现数组的深拷贝是最简单的。

var arr = [1,2,3,4,5]
var [ ...arr2 ] = arr
arr[2] = 5
console.log(arr)
console.log(arr2)
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果如下:

对象的深拷贝

对象的深拷贝相比数组也没有困难许多,列举两个方法。

万能的for循环实现对象的深拷贝

在很多时候,for循环能够解决大问题。

var obj = {
name: 'FungLeo',
sex: 'man',
old: '18'
}
var obj2 = copyObj(obj)
function copyObj(obj) {
let res = {}
for (var key in obj) {
res[key] = obj[key]
}
return res
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

转换成json再转换成对象实现对象的深拷贝

上面的代码实在是比较长,所以,用一个更暴力的方法吧!代码如下:

var obj = {
name: 'FungLeo',
sex: 'man',
old: '18'
}
var obj2 = JSON.parse(JSON.stringify(obj))
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

这个原理没什么好解释的,实在是够简单粗暴的啦!

2017年10月31日补充: 扩展运算符实现对象的深拷贝

var obj = {
name: 'FungLeo',
sex: 'man',
old: '18'
}
var { ...obj2 } = obj
obj.old = '22'
console.log(obj)
console.log(obj2)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

运行结果如下:

小结

数组和对象的深拷贝是js中最常见的应用。理解各种方法是必须的。希望对大家有所帮助。 
本文中并没有对异常进行处理,主要在讲原理。更多的数组以及对象的操作方法,可以参考lodash的源码,查看它的源码可以让你的js基础变得非常牢固。我也在学习中。

2017年10月31日补充,使用es6提供的扩展运算符的方法实现深拷贝,简单,高效。并且,对象的深拷贝不会像使用 JSON 方法深拷贝一样,丢失函数等信息,只能用来深拷贝 JSON 数据格式的对象。推荐大家使用。

补充一个数组去重的方法

function dedupe(array) {
return [...new Set(array)]
}
var arr = [1,2,2,3,3,4,4,5,5]
console.log(dedupe(arr))
  • 1
  • 2
  • 3
  • 4
  • 5

运行结果如下:

JS 数组以及对象的深拷贝总结的更多相关文章

  1. JS 数组、对象的深拷贝

    博客地址:https://ainyi.com/72 JavaScript 程序中,对于简单的数字.字符串可以通过 = 赋值拷贝 但是对于数组.对象.对象数组的拷贝,就有浅拷贝和深拷贝之分 浅拷贝就是当 ...

  2. javascript 数组以及对象的深拷贝(复制数组或复制对象)的方法

    前言 for,slice(0),concact() 在js中,数组和对象的复制如果使用=号来进行复制,那只是浅拷贝.如下图演示:  如上,arr的修改,会影响arr2的值,这显然在绝大多数情况下,并不 ...

  3. js 数组、对象转json 以及 json转 数组、对象

    let jsonObj = $.parseJSON(jsonStr); //json字符串转化成json对象(jq方法) var jsonObj = JSON.parse(jsonStr); //js ...

  4. JS数组和对象的浅拷贝和深拷贝

    共勉~ 在许多编程语言中,传递参数和赋值是通过值的直接复制或者引用复制完成的.在JavaScript中,对于值是直接进行复制还是引用复制在语法上是没有区别的,完全是根据值的类型来决定的. 在JavaS ...

  5. js数组和对象相等判断、拷贝详解(结合几个现象讲解引用数据类型的趣事)

    序言 最近遇到几个js引用数据类型造成的bug,今天结合bug详细分析一下,避免以后再犯,也希望能帮大家提个醒,强化js基本功. 目录 1.浅拷贝.深拷贝,解决变量赋值相互影响问题 2.判断2个数组. ...

  6. JS实现对对象的深拷贝

    手动遍历对象拷贝 /** * 深拷贝 * @param {*} obj 拷贝对象(object or array) * @param {*} cache 缓存数组 */ function deepCo ...

  7. js 数组、对象转json 以及json转 数组、对象

    1.JS对象转JSON 方式:JSON.stringify(obj) var json = {"name":"iphone","price" ...

  8. JS数组与对象的遍历方法大全

    本文简单解析各种数组和对象属性的遍历方法: 原生for循环.for-in及forEach ES6 for-of方法遍历类数组集合 Object.key()返回键名的集合 jQuery的$.each() ...

  9. js数组和对象的区别,ajax传入多个参数值,ajax传多个数组数据

    数组分为索引数组和关联数组 js中先声明一个空数组 arr = [] 索引数组 索引是整数,如arr[0] = 'a' 关联数组 索引是自定义的字符串,如arr['a'] = 'a' js中的对象 你 ...

随机推荐

  1. T-SQL 之 公用表表达式(CTE)

    在编写T-SQL代码时,往往需要临时存储某些结果集.在CTE之前常用的两种临时存储结果集为:临时表和表变量.除此之外,还可以使用公用表表达式的方法. 公用表表达式(Common Table Expre ...

  2. 【找规律】HDU 4662——MU Puzzle

    来源:点击打开链接 这个题目的来源是人工智能领域MU猜想.比赛的时候也参考了相关资料,可是最后差一点没有把规律推出来. 注意到以下几个性质.第一,MI怎么变换M永远只能在第一位.第二,因为变换时只能在 ...

  3. 使用hasOwnProperty监测对象是否含有某个属性

    1.示例代码 <!DOCTYPE html> <html lang="zh"> <head> <meta charset="UT ...

  4. mysql-5.7.12-winx64安装版配置、使用

    一.下载 http://dev.mysql.com/downloads/mysql/ 下载版本:Windows (x86,64-bit), ZIP Archive(mysql-5.7.12-winx6 ...

  5. Centos6 安装 Redis 和集群配置

    Redis安装 先确认gcc和tcl已经安装 sudo yum install gcc-c++ sudo yum install tcl 解压, 编译和安装 .tar.gz /usr/src/ cd ...

  6. Android开发之定位系统

    2013-07-04 定位系统 全球定位系统(Global Positioning System, GPS), 又称全球卫星定位系统. 最少只需其中3颗卫星,就能迅速确定用户组地球所处的位置及海拔高度 ...

  7. ajax提交gb2312的中文,出现乱码

    解决方案:

  8. python笔记-列表和元组

    列表和元组: -可以将列表和元组当成普通的数组 -列表和元组可以保存任意类型的python对象 -通过从0开始的数字索引访问元素 -列表和元组可以存储不同类型的对象 列表和元组的区别: -列表元素使用 ...

  9. Cocos2d-x EditBox 设置字号大小无论用问题

    1.有几次设置EditBox的字体大小无论用,于是跟进了Cocos2d-x 底层代码,看了下 原来是没设置字体的原因 以下是Editbox的setFontSize方法: void CCEditBox: ...

  10. AutoFac文档12(转载)

    目录 开始 Registering components 控制范围和生命周期 用模块结构化Autofac xml配置 与.net集成 深入理解Autofac 指导 关于 词汇表 Resolve的参数 ...