如何进行深拷贝?

深拷贝与浅拷贝

  • 浅拷贝:拷贝引用地址 (只复制指向某个对象的指针,而不复制对象本身,新旧对象共享一块内存)

    由于引用类型(object,array,function)的数据在栈里储存的只是堆地址,所以当对引用类型进行直接赋值时,实际上只复制了地址,复制出来的变量和原来的变量最终都指向同一个对象。当改变其中一个对象的属性值时,两个对象都会发生改变

  • 深拷贝:拷贝实例 (复制并创建一个一摸一样的对象,不共享内存,修改新对象,旧对象保持不变。)

  • 当修改赋值的对象 会影响原对象;修改原对象也会影响赋值的对象

  • 如果希望深拷贝,想到了使用for in的方式,但for in有自身的问题

    • 当for in 的键对应的值又是引用类型时,又会变为赋址操作;

      解决:用递归

    • 原型上的共享属性也会遍历

      解决:使用hasOwnProperty来进行判断

如何进行深拷贝

  • 原生js
  • JSON.parse(JSON.stringify(obj))
  • jq的$.extend方法:将一个或多个对象合并到目标对象
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
var obj = {
name:'joth',
age:18,
sex:'male',
arr:[1,2,3,4],
body:{
weight:'70kg',
height:'176cm',
eyes:{
left:'2.0',
right:'1.6'
}
},
fn:function(){
console.log('haha');
}
}

//方法一:原生js的深拷贝(递归)

function deepClone(obj){ //obj 原对象
var objClone = Array.isArray(obj) ? [] : {};//在函数内 要拷贝的对象
if(obj && typeof obj == 'object');{ //如果有obj 且obj是一个对象
for(var key in obj){ //进行 for in循环
if(obj.hasOwnProperty(key)){//判断该属性是否是构造函数上的属性(即不是原型上的共享属性)
if(obj[key] && typeof obj[key] == 'object'){//判断该属性对应的值是否为对象
objClone[key] = deepClone(obj[key]);//如果该属性对应的值是一个对象则再次调用该函数
}else{
objClone[key] = obj[key]; // 如果该属性对应的值不是对象,则是基本类型,直接赋值
}
}
}
}
return objClone:
}
1
2
//方法二:(不能复制函数)
var obj1 = JSON.parse(JSON.stringify(obj))
1
2
3
4
5
6
7
8
9
10
11
12
13
//方法三:jq的深浅拷贝

//浅拷贝
var obj1 = {
money: 1000
}
var obj2 = {
number: 101
}
var obj3 = $.extend({},obj1,obj2)

//深拷贝
var obj3 = $.extend(true,{},obj1)