js对象浅拷贝与深拷贝

在js中,若是一个对象,做为变量赋值给另外一个对象,那么两个对象得值会是相同得引用地址,其中一个改变,另一个也会随之改变。函数

`性能

var obj1 = {
    num: 123
}
var obj2 = obj1;
obj2.num = 456;
console.log(obj1.num);  // 输出: 456
复制代码

` 在咱们平常开发过程中,咱们去复制一个对象得目的是为了去得到该对象的值,咱们对得到的值进行操做,不会影响原对象才对。而咱们要解决这样的问题,就涉及到了使用对象的浅拷贝和深拷贝来解决问题了。spa

浅拷贝

浅拷贝是咱们平常开发使用最多的,由于他能解决咱们平常开发中绝大部分的问题,首先最经常使用的方法就是:Object.assign(),是ES6:Object里的新增方法,Object.assign()方法用于对象的合并,将源对象(source)的全部可枚举属性,复制到目标对象(target),那么如何使用呢,请看案例:3d

`code

var obj1 = {
    num: 123
}
var obj2 = Object.assign({}, obj1);
obj2.num = 456;
console.log(obj1.num, obj2.num);  // 输出: 123  456
复制代码

`cdn

使用方法,仍是很是简单的,咱们也可使用扩展运算符...的方法来实现浅拷贝: `对象

var obj1 = {
    num: 123
}
var obj2 = {...obj1};
obj2.num = 456;
console.log(obj1.num, obj2.num);  // 输出: 123  456
复制代码

` 所谓浅拷贝,实际上指的就是复制对象自己可枚举的属性,不会拷贝到继承属性和可自己可枚举属性的值也是对象里的值。blog

深拷贝

上面那句话的后半段里看上去有点绕,这里在讲什么是深拷贝,你就立马理解了。而 这个字我我的以为就挺通俗易懂了,说白了就是更深层次的拷贝呗。那么怎么就是深拷贝呢?看案例: `继承

var obj1 = {
    num: 123,
    child: {
        str: '子级对象'
    }
}
var obj2 = Object.assign({}, obj1);
obj2.child.str = '子对象的str值';
console.log(obj1.child.str);  // 输出: 子对象的str值
复制代码

`开发

经过上面的案例,咱们发现,咱们用了浅拷贝,可是obj1obj2里面的child子对象仍是共用了一个引用地址,这就是我上面说的那句“自己可枚举属性里的值也是对象”,因此咱们就须要更深层次的拷贝到这个对象里来呗,这就须要使用深拷贝了,最多见的深拷贝方法就是:JSON.parse(JSON.stringify(obj1)),下面看案例:

`

var obj1 = {
    num: 123,
    child: {
        str: '子级对象'
    }
}
var obj2 = JSON.parse(JSON.stringify(obj1));
obj2.child.str = '子对象的str值';
console.log(obj1.child.str);  // 输出: 子级对象
复制代码

`

经过使用JSON.parse(JSON.stringify(obj1))咱们实现了深拷贝,其实该方法的实现原理很是的简单,JSON.stringify()是把咱们的对象转换成了JSON字符串,字符串属于基本类型了,已经不存在引用地址了,而后咱们在用JSON,pase()把它转换回来,此时它已是一个新对象了,和原对象没有任何关系了。经过这样转换的方式实现了深拷贝。可是呢,该方法也存在必定的局限性,或者说是不足:

  • 1.会忽略 undefined,
  • 2.不能序列化函数,
  • 3.不能解决循环引用的对象

下面看案例:

`

let obj = {
    a: 1,
    b: {
        c: 2,
        d: 3,
    },
}

obj.c = obj.b
obj.e = obj.a
obj.b.c = obj.c
obj.b.d = obj.b
obj.b.e = obj.b.c
let newObj = JSON.parse(JSON.stringify(obj))
console.log(newObj)
复制代码

`

若是你的对象像这样的相互引用赋值的话,那么你会发现不能使用JSON.parse(JSON.stringify(obj1))来实现了,而且还报错:

不只如此,在遇到 undefined和函数时,也不能正常实现深拷贝:

`

let obj1 = {
    id: undefined,
    fn: function() {},
    tel: 13880089009
}
let obj2 = JSON.parse(JSON.stringify(obj1))
console.log(obj2) // {tel: 13880089009}
复制代码

`

这样只拷贝到了tel一个属性值:那么这个时候就会用到经常使用得另外一种深拷贝方式了:for in

`

let obj1 = {
	    id: undefined,
		fn: function() {},
		tel: 13880089009
	}
let obj2 = {}
    for (let key in obj1) {
		obj2[key] = obj1[key]
	}
    console.log(obj2)   // {id: undefined, fn: ƒ, tel: 13880089009}
复制代码

`

for in自己是一个比较耗性能得循环方法,它实现得方式也简单粗暴,就是一个属性一个属性得赋值,for in还能够遍历到对象继承得全部属性和方法,正是由于这一点,因此for in是个耗性能得主。

总结

本篇章主要讲解得是浅拷贝和深拷贝这样得一个概念,并给出了我的用得一些浅拷贝和深拷贝得方法,用于对咱们平常开发当中注意得一些细节操做。喜欢得朋友给个赞吧,谢谢。

相关文章
相关标签/搜索