数组和对象的拷贝

已经两个多月没写了,真是太懒了!
说起js数组的拷贝,无非是浅拷贝和深拷贝。以前对这两个概念一直很模糊,最近好像懂了一点点。

数组拷贝

浅拷贝

浅拷贝就相当于拷贝了该数组的地址,新的数组和旧数组共用一个内存,无论是修改新的数组还是旧的数组,都会影响另一个数组。最简单的浅拷贝就是直接赋值。

1
2
3
4
5
var a = ["one","two","three"];
var b = a;
b[2] = "four";
console.log("a",a);//a ["one", "two", "four"]
console.log("b",b);//b ["one", "two", "four"]

深拷贝

有时我们想修改一个拷贝数组,但又不想改动原数组,就需要使用深拷贝。深拷贝是新开辟一块内存来存放新数组。新数组或旧数组的改动都不会影响对方。下面讲几个常见的简单的数组深拷贝方法。

  • slice

我们知道使用slice会返回一个“裁剪”出来的数组。

1
2
3
4
5
var a = ["one","two","three"];
var b = a.slice(0);
b[2] = "four";
console.log("a",a);//a ["one", "two", "three"]
console.log("b",b);//b ["one", "two", "four"]
  • concat

使用concat的拷贝效果与slice相同。

1
2
3
4
5
var a = ["one","two","three"];
var b = a.concat();
b[2] = "four";
console.log("a",a);//a ["one", "two", "three"]
console.log("b",b);//b ["one", "two", "four"]

对象拷贝

浅拷贝

  • Object.assign(obj1,obj2[,…])

Object.assign()可用于对象的拷贝,深浅都行。作用与jQuery的$.extend()类似。

1
2
3
4
5
6
7
8
9
var a = {"one":"1","two":"2"};
var b = {"one":"3","two":"4"};
var c = Object.assign(a,b);//浅拷贝
console.log(a);//{"one":"3","two":"4"}
console.log(c);//{"one":"3","two":"4"}

var d = Object.assign({},a,b);//深拷贝
console.log(a);//{"one":"1","two":"2"}
console.log(d);//{"one":"3","two":"4"}
  • json方法
1
2
3
4
5
var a = {"one":"1","two":"2"};
var b = JSON.parse(JSON.stringify(a));
b.one = "3";
console.log(a);//{"one":"1","two":"2"}
console.log(b);//{"one":"3","two":"2"}
  • $.extend()
1
jQuery.extend( [deep], target, object1 [, objectN ] )

最后要说的是jQuery的$.extend()。当初我在学习jQuery插件的制作时就领略过它的魅力,当时就记得它可以无限覆盖自定义参数,其实就是浅拷贝,将后面的参数全都弄到第一个参数里(深浅拷贝的布尔值不写的情况下,默认是浅拷贝)。
但是当我们填写了深浅拷贝的布尔值作为第一个参数时,它就可以决定要深拷贝还是浅拷贝。true为深,false为浅。