之前对深拷贝,浅拷贝一直很头疼,一看到这些字眼,就揪心。于是就不断地查资料,查资料,查资料。。。好在现在算是搞清楚了。写在这希望能帮助到和我有同样疑惑的人们,同样也以防以后自己又给忘掉再次揪心,,,哈哈哈,好了皮一下,言归正传。对于浅拷贝,深拷贝,他俩的最大区别 请看斜体字部分,下面就一一了解。
一. 什么是拷贝?
答:拷贝就是我们常说的复制或者克隆一个对象。其中拷贝分为浅拷贝和深拷贝。
二..什末是浅拷贝?
答:浅拷贝就是对内存地址的拷贝,使得‘拷贝出来’的和‘原来的’指向的是同一内存地址,它对于对象只是简单的引用而已,只能拷贝一层,不能对子对象进行拷贝。导致拷贝完后前后两个对象相互影响,就是你变我也变,这样在实际开发过程中很不好。如果还没理解,那就看看下面的例子:
1.普通对象
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
var obj1 = obj;
obj1.sex='女';
console.log(obj1,obj);
//打印出结果为:
obj1:{name: "du", age: 21, borther: {…}, sex: "女"}
obj:{name: "du", age: 21, borther: {…}, sex: "女"}
由此看出在obj1发生改变时,obj也发生了相应的改变。这样就局限了好多。。。。
2.数组对象
var arr=[1,2,3,{a:6}];
var arr1=arr.concat();
arr1[3].b=7;
arr[3].c=8;
console.log(arr,arr1);
//打印出结果为
arr: [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)
arr1: [1, 2, 3, {…}]0: 11: 22: 33: {a: 6, b: 7, c: 8}length: 4__proto__: Array(0)
由此看出在数组里面也是如此。。。。。这就是浅拷贝。
三.什末是深拷贝?
答:深拷贝就是对对象中的子对象进行递归拷贝,复制,拷贝后两个对象相互不受影响。因为他们会有不同的地址,会在堆中有不同的内存,简短话总结 就是拥有相同的值,不同的地址。下面写个例子,就拿JSON.parse()/JSON.stringify()会更清楚。
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
//JSON.stringify()是将json对象转换为字符串型,JSON.parse()是将字符串转换为json对象
var obj1=JSON.parse(JSON.stringify(obj));
obj1.sex='女';
obj.borther.sex='男';
console.log(obj1,obj);
//打印出来结果为
obj1:{name: "du", age: 21, borther: {…}, sex: "女"} //注意对象的属性
borther:{name: "rui", age: 12} //注意子对象borther的结果
obj: {name: "du", age: 21, borther: {…}} //注意对象的属性
borther:{name: "rui", age: 12, sex: "男"} //注意子对象borther的结果
由此看出在obj1发生改变时,obj并没有改变,obj发生改变时,obj1并没有改变,这就是深拷贝。
四. 深克隆的封装
那末看了这些肯定都懂了什末是浅拷贝,深拷贝和他们之间的区别了。但是不足一点就是在深拷贝中只看到了json数据用法,那末能不能封装一个深拷贝的方法呢,还真有,哈哈哈哈哈哈,且看下面
在实现深度拷贝时,你得先在脑子中构建出一个思路框架出来,就是怎末弄,为什末这样弄。。。
1.先得遍历对象,这是毋庸置疑的
2.判断是不是原始值 typeof() -->object
3.判断是数组还是对象 (方法有instanceof / toString / constructor)
4.建立相应的数组或对象
5.递归
有了这些思路后,写起代码就容易多了
function deepClone(origin ,target){
var target = target||{}; //以防用户没传,默认是对象
for(var prop in origin){
//hasOwnProperty是用来判断某个属性是不是在对象自己的属性,它不会检测到原型链上去
if(origin[prop]!==null&&origin.hasOwnProperty(prop)){ //一定得确定对象上的属性不是原型链上的
if(typeof(origin[prop])=='object'){ //判断是不是原始值
//在不是原始值的情况下,判断是数组还是对象
target[prop] = Object.prototype.toString.call(origin[prop])=='[object Array]'?[]:{};
deepClone(origin[prop],target[prop]);
}else{
target[prop]=origin[prop];
}
}
}
return target;
}
var obj={
name:'du',
age:21,
borther:{
name:'rui',
age:12
}
};
var obj1=deepClone(obj,obj1);
obj1.sex='女';
obj.borther.sex='男';
console.log(obj1,obj);
//打印结果为
obj1: {name: "du", age: 21, borther: {…}, sex: "女"}
其中borther: {name: "rui", age: 12}
obj: {name: "du", age: 21, borther: {…}}
其中borther: {name: "rui", age: 12, sex: "男"}
由此看出,互不影响。一个深拷贝就封装完成了。