一、Object.assign()对象的拷贝
Object.assign()方法用于将所有可枚举属性的值从一个或多个源对象复制到目标对象。它将返回目标对象。Object.assign(target,...sources)【target:目标对象】,【souce:源对象(可多个)】举个栗子:constobject1={a:1,b:2,c:3};constobject2=Object.assign({c:4,d:5},object1);console.log(object2.c,object2.d);console.log(object1)// { a: 1, b: 2, c: 3 }console.log(object2)// { c: 3, d: 5, a: 1, b: 2 }注意:1.如果目标对象中的属性具有相同的键,则属性将被源对象中的属性覆盖。后面的源对象的属性将类似地覆盖前面的源对象的属性2.Object.assign 方法只会拷贝源对象自身的并且可枚举的属性到目标对象。该方法使用源对象的[[Get]]和目标对象的[[Set]],所以它会调用相关 getter 和 setter。因此,它分配属性,而不仅仅是复制或定义新的属性。如果合并源包含getter,这可能使其不适合将新属性合并到原型中。为了将属性定义(包括其可枚举性)复制到原型,应使用Object.getOwnPropertyDescriptor()和Object.defineProperty()。
二、Object.assign()对象的深拷贝
针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是属性值。假如源对象的属性值是一个对象的引用,那么它也只指向那个引用。letobj1={a:0,b:{c:0}};letobj2=Object.assign({},obj1);console.log(JSON.stringify(obj2));// { a: 0, b: { c: 0}} obj1.a=1;console.log(JSON.stringify(obj1));// { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2));// { a: 0, b: { c: 0}} obj2.a=2;console.log(JSON.stringify(obj1));// { a: 1, b: { c: 0}} console.log(JSON.stringify(obj2));// { a: 2, b: { c: 0}}obj2.b.c=3;console.log(JSON.stringify(obj1));// { a: 1, b: { c: 3}} console.log(JSON.stringify(obj2));// { a: 2, b: { c: 3}} 最后一次赋值的时候,b是值是对象的引用,只要修改任意一个,其他的也会受影响// Deep Clone (深拷贝)obj1={a:0,b:{c:0}};letobj3=JSON.parse(JSON.stringify(obj1));obj1.a=4;obj1.b.c=4;console.log(JSON.stringify(obj3));// { a: 0, b: { c: 0}}
3、对象的合并
consto1={a:1};consto2={b:2};consto3={c:3};constobj=Object.assign(o1,o2,o3);console.log(obj);// { a: 1, b: 2, c: 3 }console.log(o1);// { a: 1, b: 2, c: 3 }, 注意目标对象自身也会改变。其实就是对象的拷贝,o1就是目标对象,后面的是源对象,后面的属性等会拷贝到目标对象
4、合并具有相同属性的对象
consto1={a:1,b:1,c:1};consto2={b:2,c:2};consto3={c:3};constobj=Object.assign({},o1,o2,o3);console.log(obj);// { a: 1, b: 2, c: 3 }1.属性被后续参数中具有相同属性的其他对象覆盖。2.目标对象的属性与源对象的属性相同,源的会覆盖目标的属性
5.继承属性和不可枚举属性是不能拷贝
constobj=Object.create({foo:1},{// foo 是个继承属性。bar:{value:2// bar 是个不可枚举属性。},baz:{value:3,enumerable:true// baz 是个自身可枚举属性。}});创建对象时,如果没有设置enumerable的值,默认为false(不可枚举属性),设置为true,则为可枚举属性constcopy=Object.assign({},obj);console.log(copy);// { baz: 3 }
6.原始类型会被包装为对象
constv1="abc";constv2=true;constv3=10;constv4=Symbol("foo")constobj=Object.assign({},v1,null,v2,undefined,v3,v4);// 原始类型会被包装,null 和 undefined 会被忽略。// 注意,只有字符串的包装对象才可能有自身可枚举属性。console.log(obj);// { "0": "a", "1": "b", "2": "c" }
7.异常会打断后续拷贝任务
consttarget=Object.defineProperty({},"foo",{value:1,writable:false});// target 的 foo 属性是个只读属性。Object.assign(target,{bar:2},{foo2:3,foo:3,foo3:3},{baz:4});// TypeError: "foo" is read-only// 注意这个异常是在拷贝第二个源对象的第二个属性时发生的。console.log(target.bar);// 2,说明第一个源对象拷贝成功了。console.log(target.foo2);// 3,说明第二个源对象的第一个属性也拷贝成功了。console.log(target.foo);// 1,只读属性不能被覆盖,所以第二个源对象的第二个属性拷贝失败了。console.log(target.foo3);// undefined,异常之后 assign 方法就退出了,第三个属性是不会被拷贝到的。console.log(target.baz);// undefined,第三个源对象更是不会被拷贝到的。
作者:Amy_yqh
链接:https://www.jianshu.com/p/f9ec860ecd81
来源:简书
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。