JavaScript中的深浅复制
2017-08-15 本文已影响52人
baiying
什么是深浅复制
- 浅复制:浅复制就是复制一份引用,所有的引用对象都指向同一份数据,并且都可以修改这份数据.
- 深复制:所谓”深拷贝”,就是能够实现真正意义上的数组和对象的拷
var a = 5;
var b = a;
b = 1;
console.log(a);//5
console.log(b);//1
var a = {name:tom};
var b = a;
b.name = 'lisa';
console.log(a.name);//lisa
console.log(b.name);//lisa
由上述代码可见,基本类型的赋值是深复制,引用类型的赋值是浅复制
如何实现引用类型深复制
浅复制是非常简单的,那么对于引用类型来说要如何实现深复制呢
Object.assign()
方法(一层深复制)
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var newObj = Object.assign({},obj);
console.log(newObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(newObj);
//第一个输出结果
{
age: 10,
like: [object Object] {
fruit: "apple"
},
name: "tom"
}
//第二个输出结果
{
age: 10,
like: [object Object] {
fruit: "peach"
},
name: "tom"
}
我们看到对象的第一层的属性值的修改并不会互相影响,也就是说他们占用的是不同的内存,但是第二层的属性值的修改却会互相影响,所以第二层复制过来得只是对象的引用,他们是指向同一块内存的
因此:Object.assign()
方法只实现了对象第一层的深复制,更深层的都是浅复制.
-
JSON
对象的json.stringify()
方法和json.parse()
方法-
json.stringify()
:将js对象转换成字符串对象 -
json.parse()
:将字符串对象转换成js对象
-
var obj = {name:'tom',age:10,like:{fruit:'apple'}};
var strObj = JSON.stringify(obj);
var jsObj = JSON.parse(strObj);
obj.name = 'lisa';
obj.like.fruit = 'peach';
console.log(jsObj);
//输出结果
{
age: 10,
like: [object Object] {
fruit: "apple"
},
name: "tom"
}
我们看到在obj上的修改都不会影响到最终的jsObj,所以结合这两个方法可以轻松实现对象的深复制.
-
原生js实现深拷贝
思路:如果对象属性值是基本类型则直接赋值(前边提过,基本类型的赋值属于深拷贝)如果对象是引用类型,则递归至基本类型再赋值
function deepCopy(p,c) {
if(p === null || typeof p !== "object"){//非引用类型的深拷贝直接赋值
return p;
}
var c = c || {};
for (var i in p) {//引用类型,遍历属性
if (typeof p[i] === 'object') { //属性值是引用类型
c[i] = (p[i].constructor === Array) ? [] : {};//属性值是数组还是对象决定递归时传入的c[i]是[]还是{}
deepCopy(p[i], c[i]);//递归拷贝
} else {
c[i] = p[i];//属性值是基本类型,直接赋值
}
}
return c;
}
var target = {name:'tom',age:1,like:{fruit:['apple','peach']}};
var copyObj = (deepCopy(target));
console.log(copyObj);
target.name = 'lisa';
target.like.fruit = ['apple'];
console.log(copyObj);
//第一次输出结果
{
age: 1,
like: [object Object] {
fruit: ["apple", "peach"]
},
name: "tom"
}
//第二次输出结果
{
age: 1,
like: [object Object] {
fruit: ["apple", "peach"]
},
name: "tom"
}
我们可以看到上述代码实现了对象的深拷贝,拷贝后两个对象的修改并不会相互影响.