javascript 数组以及对象的深拷贝的方法

来源:互联网 发布:effective java 知乎 编辑:程序博客网 时间:2024/06/02 02:15

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] = 5console.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] = 5console.log(arr)console.log(arr2)
  • 1
  • 2
  • 3
  • 4
  • 5

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

ES6扩展运算符实现数组的深拷贝

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

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

运行结果如下:

ES6扩展运算符实现数组的深拷贝

=====多维数组的深拷贝=====

因为javascript分原始类型与引用类型(与java、c#类似)。Array是引用类型,所以直接用=号赋值的话,只是把源数组的地址(或叫指针)赋值给目的数组,并没有实现数组的数据的拷贝。另外对一维数组和多维数据的深拷贝实现方式是不一样的

多维数组深拷贝的JS函数实现方式:

复制代码
    function deepcopy(obj) {            var out = [],i = 0,len = obj.length;            for (; i < len; i++) {                if (obj[i] instanceof Array){                    out[i] = deepcopy(obj[i]);                }                else out[i] = obj[i];            }            return out;        }         //下面是测试代码             var weekArray = new Array(7);//数组第一维        var timeTableArray = new Array();  //数组第二维        var lineArray = new Array(4);  //数组第三维                lineArray[0] = "1_a";        lineArray[1] = "1_b";        lineArray[2] = "1_c";        timeTableArray.push(lineArray);        weekArray[0] = deepcopy(timeTableArray);                        //清空,并添加其他星期的数据        lineArray.splice(0,lineArray.length);        timeTableArray.splice(0,timeTableArray.length);                lineArray[0] = "7_a";        lineArray[1] = "7_b";        lineArray[3] = "7_d";        timeTableArray.push(lineArray);        weekArray[7] = deepcopy(timeTableArray);                alert("weekArray=" + weekArray[0]);//返回 "1_a,1_b,1_c,"        alert("weekArray=" + weekArray[7]);//返回 "7_a,7_b,,7_d"
复制代码

 

  多维数组的jquery实现方式:

   把上述的deepcopy函数用下面的函数替代即可

  weekArray[0] = $.extend(true, {}, timeTableArray);


对象的深拷贝

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

万能的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

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

扩展运算符实现对象的深拷贝

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

运行结果如下:

扩展运算符实现对象的深拷贝

小结

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

首发链接:http://blog.csdn.net/fungleo/article/details/54931379