js中的浅复制和深复制

在很多情况下,我们需要在不影响原数组的情况下 操作数组,这时候就需要对目标数组进行复制,下面看看 js 中复制的两种形式。

js中的浅复制和深复制

浅?深?

这个深浅 ,应该就是字面上的意思 ,复制的深浅。

加入一个数组 有多层,浅复制的话 ,只是复制了这个 数组的第一层 ,数组里面的 还是指向原来数组里面对应的,修改了一个,两个数组都会改变

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
var one = [
[1,2,3],
[4,5,6],
[7,8,9]
]
var two = one.slice();
/** two
[
[1,2,3],
[4,5,6],
[7,8,9]
]

**/

two[0][0] = 111;

/** one two
[
[111,2,3],
[4,5,6],
[7,8,9]
]

这种影响只限于 修改原来数组已有的 部分 如果向 two里面新加一个,则不会影响one

**/

two.push([1,1,1])

/** one :
[
[111,2,3],
[4,5,6],
[7,8,9]
]

two :
[
[111,2,3],
[4,5,6],
[7,8,9],
[1,1,1]
]

**/

类似的还有对象。

深复制和浅复制最根本的区别在于是否是真正获取了一个对象的复制实体,而不是引用。

为了避免这种现象 ,就需要使用 深复制,它能避免出现这种修改原数组的现象。

接下来 看看 两种复制方式 的具体实现方法。

浅复制

  • 1-直接用 =

这种方法只使用与 字符串 或者数字的复制,数组或对象使用 = 是复制的引用,指向的还是同一个东西的。

  • 2-数组
    • slice()
    • var b = […a]; // 解构赋值
    • Array.from // ES6 新增的 Array 方法
    • concat()

这种方法 适用于一阶数组 。二阶以上就不管用了。

  • 3-对象

使用一层循环 把 目标对象里面的属性全都复制到一个新的对象里面去

1
2
3
4
var res = {};
for(var key in object){
res[key] = object[key];
}

但是这只适用 于 一层 如果对象里面的某个属性的值 还是对象 ,那就不适用了。

深复制

深复制的情况一般见于 多阶数组或者多阶对象。

无论是数组还是对象,都需要用循环和递归 来讲其中的每一个属性值 复制到另一个 数组或对象里面。

下面这个方法可以深复制 数组或对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var cloneObj = function(obj){
var str, newobj = obj.constructor === Array ? [] : {};
if(typeof obj !== 'object'){
return;
} else if(window.JSON){
str = JSON.stringify(obj), //系列化对象
newobj = JSON.parse(str); //还原
} else {
for(var i in obj){
newobj[i] = typeof obj[i] === 'object' ?
cloneObj(obj[i]) : obj[i];
}
}
return newobj;
};


// 来源 https://www.zhihu.com/question/23031215

还有一个特别的技巧

那就是 把对象转字符串在转对象:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
var a =[
[1,2,3],
[4,5,6],
[7,8,9]
];

var b = JSON.parse(JSON.stringify(a));

b[0][0] = 111;
/*
a : [
[1,2,3],
[4,5,6],
[7,8,9]
]

b : [
[111,2,3],
[4,5,6],
[7,8,9]
]

*/

总结

  1. 字符串 ,数字的 复制 用 = 就可以了
  2. 一维数组 用 slice 、concat 、[…] 或者 Array.from 都可以
  3. 多维数组 或 对象 普遍用神技 JSON.parse(JSON.stringify());
    of course 如果你不嫌麻烦的话 可以写一个递归的方法来深复制。

2017/10/26 下午5:13:01 哞