使用slice和concat对数组的深拷贝和浅拷贝
一、数组浅拷贝
在使用JavaScript对数组进行操作的时候,我们经常需要将数组进行备份.
如下代码,如果只是简单才用赋值的方法,那么我们只要更改其中的任何一个,然后其他的也会跟着改变,这就导致了问题的发生
var arr1 = ["red","yellow","black"];
var arr2 = arr1;
arr2[1] = "green";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2);
测试结果如下

像上面的这种直接赋值的方式就是数组的浅拷贝,浅拷贝改变其中一个数组,另外一个数组也会跟着改变。很多时候,这不是我们想要的。
二、数组深拷贝方法
(1)js的slice方法
对于array对象的slice函数,返回一个数组的一段。(仍为数组)
arrayObj.slice(start, [end])
参数:
arrayObj 必选项。一个 Array 对象。
start 必选项。arrayObj 中所指定的部分的开始元素是从零开始计算的下标。
end可选项。arrayObj 中所指定的部分的结束元素是从零开始计算的下标。
说明:
slice 方法返回一个 Array 对象,其中包含了 arrayObj 的指定部分。
slice 方法一直复制到 end 所指定的元素,但是不包括该元素。
如果 start 为负,将它作为 length + start处理,此处 length 为数组的长度。
如果 end 为负,就将它作为 length + end 处理,此处 length 为数组的长度。
如果省略 end ,那么 slice 方法将一直复制到 arrayObj 的结尾。
如果 end 出现在 start 之前,不复制任何元素到新数组中。
测试例子:
var arr1 = ["1","2","3"];
var arr2 = arr1.slice(0);
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );
测试结果:

如测试结果显示,通过JS的slice方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响。
(2)js的concat方法
concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组,而仅仅会返回被连接数组的一个副本。
语法:arrayObject.concat(arrayX,arrayX,......,arrayX)
说明:返回一个新的数组。该数组是通过把所有 arrayX 参数添加到 arrayObject 中生成的。如果要进行 concat() 操作的参数是数组,那么添加的是数组中的元素,而不是数组。
测试例子:
var arr1 = ["1","2","3"];
var arr2 = arr1.concat();
arr2[1] = "9";
console.log("数组的原始值:" + arr1 );
console.log("数组的新值:" + arr2 );
测试结果:

如测试结果显示,通过JS的concat方法,改变拷贝出来的数组的某项值后,对原来数组没有任何影响。
(3)js遍历数组的方法
测试例子:
var arr1 = [1,2,3];//原来数组
var arr2 = [];//新数组
function deepCopy(arry1, arry2){
var length = arry1.length;
for(var i = 0;i<length;i++){
arry2[i] = arry1[i];
}
}
deepCopy(arr1, arr2);
arr2[0] =5;
console.log(arr1);
console.log(arr2);
测试结果:

三、slice,concat方法的局限性
测试例子1
var arr1 = [{"name":"weifeng"},{"name":"boy"}];//原数组
var arr2 = [].concat(arr1);//拷贝数组
arr1[1].name="girl";
console.log(arr1);// [{"name":"weifeng"},{"name":"girl"}]
console.log(arr2);//[{"name":"weifeng"},{"name":"girl"}]
测试结果:

测试例子2
var a1=[["1","2","3"],"2","3"],a2;
a2=a1.slice(0);
a1[0][0]=0; //改变a1第一个元素中的第一个元素
console.log(a2[0][0]); //影响到了a2 var b1=[["1","2","3"],"2","3"],b2;
b2=b1.slice(0);
b1[0][0]=0; //改变a1第一个元素中的第一个元素
console.log(b2[0][0]); //影响到了a2
测试结果:

从上面两个例子可以看出,由于数组内部属性值为引用对象,因此使用slice和concat对对象数组的拷贝,整个拷贝还是浅拷贝,拷贝之后数组各个值的指针还是指向相同的存储地址。
因此,slice和concat这两个方法,仅适用于对不包含引用对象的一维数组的深拷贝
使用slice和concat对数组的深拷贝和浅拷贝的更多相关文章
- javascript对象和数组之 深拷贝和浅拷贝
管是在面试中还是我们的项目中经常会用到数组或者对象的深拷贝,下面我就自己总结的分享给大家. 首先要知道什么是深拷贝?什么是浅拷贝? 深拷贝:源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另外 ...
- javascript中slice() splice() concat()操作数组的方法
这三个操作数组,哪个返回一个新数组呢.上代码 splice()方法,用于插入,删除和替换. var arr=[1,2,3,4,5]; var arr1=arr.splice(1,3); console ...
- 理解JavaScript中的深拷贝和浅拷贝
, num2 = num1;console.log(num1) //1console.log(num2) //1num2 = 2; //修改num2console.log(num1) //1conso ...
- 低门槛彻底理解JavaScript中的深拷贝和浅拷贝
作者 | 吴胜斌 来源 | https://www.simbawu.com/article/search/9 在说深拷贝与浅拷贝前,我们先看两个简单的案例: //案例1var num1 = 1, nu ...
- 在js中如何区分深拷贝与浅拷贝?
一.自我理解 简单来讲就是:深拷贝层层拷贝,浅拷贝只拷贝第一层. 在深拷贝中,新对象中的更改不会影响原对象,而在浅拷贝中,新对象中的更改,原对象中也会跟着改. 在深拷贝中,原对象与新对象不共享相同的属 ...
- js 中多维数组的深拷贝的多种实现方式
因为javascript分原始类型与引用类型(与java.c#类似).Array是引用类型,所以直接用=号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝.另外对一维 ...
- javascript中数组的深拷贝的方法
一.什么是浅拷贝 在js当中,我们常常遇到数组复制的的情况,许多人一般都会使用"="来直接把一个数组赋值给一个变量,如 var a=[1,2,3]; var b=a; consol ...
- JavaScript中对象和数组的深拷贝
不管是在面试中还是我们的项目中经常会用到数组或者对象的深拷贝,下面我就自己总结的分享给大家. 首先要知道什么是深拷贝?什么是浅拷贝? 深拷贝:源对象与拷贝对象互相独立,其中任何一个对象的改动都不会对另 ...
- JS中多维数组的深拷贝的多种实现方式
因为javascript分原始类型与引用类型(与java.c#类似).Array是引用类型,所以直接用=号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝.另外对一维 ...
随机推荐
- PowerPoint实用知识
纯手打,可能有错别字,使用的版本是office2013 转载请注明出处 http://www.cnblogs.com/hnnydxgjj/p/6347256.html ,谢谢 母版的使用 制作PPT的 ...
- spring MVC cors跨域实现源码解析
# spring MVC cors跨域实现源码解析 > 名词解释:跨域资源共享(Cross-Origin Resource Sharing) 简单说就是只要协议.IP.http方法任意一个不同就 ...
- Linux编程之从零开始搭建RPC分布式系统
我一毕业进公司就接触到了RPC,主要是使用前辈们搭建好的RPC框架以及封装好的RPC函数进行业务开发,虽说使用RPC框架开发已经近半年了,但一直想知道如何从零开始搭建起这么一个好用的分布式通信系统框架 ...
- ArcGIS制图表达Representation实战篇1-边界线和行道树制作
ArcGIS制图表达Representation实战篇1-边界线和行道树制作 by 李远祥 即便是有了一些制图表达的基础,很多人还是对ArcGIS制图表达理解停留在表面,因为没有实际的强化训练是很难体 ...
- Android 友盟分享详细集成过程及所遇问题解决
最近项目需要针对微信.朋友圈.QQ.QQ空间集成友盟分享的功能,说实话,我也是第一次做,期间碰到过很多问题,这篇随笔就来写一下我是怎么集成友盟分享的,还有碰到哪些问题,都是怎样解决的! 其实集成友盟并 ...
- Linux驱动技术(四) _异步通知技术
异步通知的全称是"信号驱动的异步IO",通过"信号"的方式,放期望获取的资源可用时,驱动会主动通知指定的应用程序,和应用层的"信号"相对应, ...
- 用VUEJS做一个网易云音乐
前言:自己学习VUEJS也一段时间,但一直没有做出来一东西.我自己一直喜欢用网易云音乐app,于是乎就做了这个app. 项目截图 技术栈 vue全家桶 (vue vue-router vuex) ax ...
- 读书笔记 effective c++ Item 12 拷贝对象的所有部分
1.默认构造函数介绍 在设计良好的面向对象系统中,会将对象的内部进行封装,只有两个函数可以拷贝对象:这两个函数分别叫做拷贝构造函数和拷贝赋值运算符.我们把这两个函数统一叫做拷贝函数.从Item5中,我 ...
- winsshfs的快速入手
之前在公司使用mac ,并且通过mac下的osfuse和sshfs连接,直接将虚拟机的文件目录同步到了本地,并且可以进行实时操作修改,对于写项目,确实是省了很大一部分上传的精力. 于是在自己的win下 ...
- FastDFS+Nginx部署详细教程
本例使用到的所有tar和zip包地址:http://download.csdn.net/detail/corey_jk/9758664 本例中使用CentOS1.CentOS2两台机器实现. 1 GC ...