# 深浅拷贝
深拷贝: 是JS中相对于Array, Object这类复杂对象,浅复制在这类复杂对象中只会赋值一层对象的属性,深拷贝则会递归的复制所有层级
# 深拷贝的两种实现
# 循环递归实现
var a = {
name:"mary",
age:20,
friend:{
name:"哈哈",
age:19,
hobby:"eat"
}
}
function deep(obj){
var newobj = {};
for(var key in obj){
// 此处遍历的key包括了实例对象和它原型的属性,所以要用hasOwnProperty进行筛选(node环境不会,浏览器环境会列举原型属性)
if(obj.hasOwnProperty(key)){
// 如果是基本类型则进行复制
if(typeof obj[key] === "number" || typeof obj[key] === "string" || typeof obj[key] === "boolean" || obj[key] === undefined || obj[key] === null){
newobj[key] = obj[key];
// 如果不是则为array或者object,仍然需要深层次的递归复制
}else{
newobj[key] = deep(obj[key]);
}
}
}
return newobj;
}
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
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
# JSON转化实现
var obj = {
name : "haha",
age :"16",
hobby : "football"
}
var text = JSON.stringify(obj); //得到一个字符串
JSON.parse(text); //重新将字符串生成一个对象,和原来的没有任何关系
1
2
3
4
5
6
7
2
3
4
5
6
7
# 浅拷贝
# 对象字面量扩展实现
const deepClone = (obj) => ({
__proto__:Object.getPrototypeOf(obj),
...obj
})
1
2
3
4
2
3
4
# 最简单的实现
function shallowClone(copyObj) {
var obj = {};
for ( var i in copyObj) {
obj[i] = copyObj[i];
}
return obj;
}
var x = {
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
var y = shallowClone(x);
console.log(y.b.f === x.b.f); // true
1
2
3
4
5
6
7
8
9
10
11
12
13
14
2
3
4
5
6
7
8
9
10
11
12
13
14
var x = {
a: 1,
b: { f: { g: 1 } },
c: [ 1, 2, 3 ]
};
var y = Object.assign({}, x);
console.log(y.b.f === x.b.f); // true
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
# 在框架中的深浅复制
# underscore
_.clone = function(obj) {
if(!_.isObject(obj)) return obj;
return _.isArray ? obj.slice() : _.extend({}, obj)
}
1
2
3
4
2
3
4
我们可以看出,在判断完obj不为复杂对象后,我们直接返回值即可,不需要深复制
如果不为简单对象,这个时候我们将判断其是否为数组,然后返回数组的slice结果,否则返回Object.assign({}, obj)
我们可以看出,在underscore中,clone不是深复制
# jQery
$.extend({}, x) // shallow copy
$.extend(true, {}, x) // deep copy
1
2
3
2
3