@xunuo
2018-12-13T15:45:03.000000Z
字数 1670
阅读 923
前端
深浅拷贝:实质上就是由于js对于基本类型和引用类型的处理不同
js不允许我们直接操作内存中的地址,也就是不能操作对象的内存空间,所以我们对 对象的操作都只是在操作它的引用。
复制也是一样:
如果复制一个基本类型的值时,会创建一个新值,并把它保存在新的变量的位置上。
如果复制的是一个引用类型时,同样会把变量中的值复制一份到新的变量空间中,但此时复制的东西并不是变量本身,而是指向该对象的指针,如果我们复制引用类型后,两个变量其实是指向同一个对象,若改变其中一个对象,则会影响另一个对象的值,如:
var num = 10;
var obj = {
name: 'lucy'
}
var num1 = num;
var obj1 = obj;
num1 = 100;
console.log('num:'+num +';num1:'+num1);//num:10;num1:100
obj1.name = 'lisa';
console.log('obj1:'+obj1.name+';obj:'+obj.name);//obj1:lisa;obj:lisa
如上代码,当obj1的name改变时obj的name也会随着改变。
如果我们要赋值对象的所有属性都不是引用类型时,就可使用浅拷贝,实现方式为直接遍历对象将其属性复制即可,然后返回新的对象。即:
function shallowCopy(obj){
var copy = {};
//只复制可遍历的属性
for(var i in obj){
//hasOwnProperty:查看该属性是否存在当前对象中
if(obj.hasOwnProperty(i))
copy[i] = obj[i];
}
return copy;
}
因为浅复制只会将对象的各个属性进行依次复制,并不会进行递归复制,而js存储对象都是存储地址的,所以浅复制会导致两个对象指向同一块内存地址。
js内部实现了浅拷贝如:Object.assign()
var newObj = Object.assign({},originObj);
newObj
是新的对象,将{}
和originObj
的内容复制到newObj
中。其中,{}
是最终复制的目标对象,originObj
是即将复制的原对象。另外还有[].slice()方法也可以实现浅拷贝:
var arr = new Array();
var arr1 = arr.slice(1,3);
//表示将arr[1]到arr[2]的内容复制到arr1中
深拷贝不仅将原对象的各个属性逐个复制出去,而且将原对象各个属性所包含的对象也依次采用深拷贝的方法递归复制到新对象上。就不会存在浅拷贝时两个对象指向同一个内存地址的问题。
但如果属性对象较大,层级较多,深拷贝会带来性能上的问题。
如递归拷贝的方法:
function deepCopy(origin,copy){
var copy = copy || {};
for(var i in origin){
if(typeof(origin[i] === 'object' )){//判断是不是一个对象
if(origin[i].constructor == 'Array'){//判断是不是数组
copy[i] = [];
}
else{
copy[i] = {};
}
deepCopy(origin[i],copy[i]);//递归
}
else
copy[i] = oringin[i];
}
return copy;
}
通过JSON解析解决
var test ={
name:{
xing:{
first:'张',
second:'李'
},
ming:'老头'
},
age :40,
friend :['隔壁老王','宋经纪','同事']
}
var result = JSON.parse(JSON.stringify(test));
result.age = 30;
result.name.xing.first = '往';
result.friend.push('fdagldf;ghad');
console.dir(test);//打印出test的所有属性和方法
console.dir(result);