Object.assign方法用于将所有可枚举属性的值从一个或多个源对象分配到目标对象,并返回目标对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| const target = { a: 1, b: 2 }; const resourceObject = { b: 4, c: 5 }; const resourceObject1 = { d: 6 }; const returnObject = Object.assign(target, resourceObject, resourceObject1); console.log(target); console.log(returnObject);
|
语法:Object.assign(target,…resource);
参数:
- target:目标对象
- resource:源对象
返回值:目标对象
描述:如果目标对象和源对象有相同属性,则目标对象属性值会被源对象覆盖,相应的后面的源对象的属性会覆盖前面源对象的属性
Object.assign只会拷贝源对象自身的并且可枚举属性到目标对象上。该方法使用源对象的getter方法和目标对象的setter方法。因此他分配属性不仅仅是复制或定义新的属性。
如果合并源包含getter,可能不适合将新属性合并到原型上,为了将属性定义复制到原型,应使用Object.defineProperty和Object.getOwnPropertyDescriptor()
注意,Object.assign不会在源对象属性值为null或undefined时抛出错误
1 2 3 4 5 6 7 8
| const a = { test:null } const b = { foo:undefined } Object.assign(a,b)
|
String和Symbol类型的属性都会被拷贝.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| const a = { a: 1, b: 2 }; const b = { c: Symbol.for(1), d: String('aaa') }; Object.defineProperty(b, 'b', { writable: false, value: 4 }); const c = Object.assign(a, b); console.log(c);
const c = Object.assign(b,a);
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const aa = { a: 'a' }; const bb = {}; Object.defineProperty(bb, 'b', { get: function() { return 'i am b' } }); const cc = Object.assign(aa, bb); console.log(cc);
|
深拷贝问题:
针对深拷贝,需要使用其他办法,因为 Object.assign()拷贝的是(可枚举)属性值。
假如源值是一个对象的引用,它仅仅会复制其引用值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| const log = console.log; const stringify = JSON.stringify
function test() { 'use strict'; let obj1 = { a: 0, b: { c: 0 } }; let obj2 = Object.assign({}, obj1); log(stringify(obj2));
obj1.a = 1; log(stringify(obj1)); log(stringify(obj2));
obj2.a = 2; log(stringify(obj1)); log(stringify(obj2));
obj2.b.c = 3; log(stringify(obj1)); log(stringify(obj2));
obj1 = { a: 0, b: { c: 0 } }; let obj3 = JSON.parse(JSON.stringify(obj1)); obj1.a = 4; obj1.b.c = 4; log(stringify(obj3)); } test();
|
合并对象
1 2 3 4 5 6 7 8 9 10 11 12 13
| const o1 = { a: 1 }; const o2 = { b: 2 }; const o3 = { c: 3 }; const obj4 = Object.assign(o1, o2, o3); console.log(obj4); console.log(o1);
|
合并具有相同属性的对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| const oo1 = { a: 1, b: 1, c: 1 }; const oo2 = { b: 2, c: 2 }; const oo3 = { c: 3 };
const obj5 = Object.assign({}, oo1, oo2, oo3); console.log(obj5);
|
拷贝 symbol 类型的属性
1 2 3 4 5 6 7 8 9 10
| const v1 = { a: 1 }; const v2 = { [Symbol('foo')]: 2 };
const obj6 = Object.assign({}, v1, v2); console.log(obj6); console.log(Object.getOwnPropertySymbols(obj6));
|
继承属性和不可枚举属性是不能拷贝的
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const obj7 = Object.create({ foo: 1 }, { bar: { value: 2 }, baz: { value: 3, enumerable: true } });
const copy = Object.assign({}, obj7); console.log(copy);
|
原始类型会被包装为对象
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| const m1 = 'abc'; const m2 = true; const m3 = 10; const m4 = Symbol('foo'); const res = Object.assign({}, m1, null, m2, undefined, m3, m4); console.log(res);
console.log(typeof res) console.log(res instanceof String);
const res1 = Object.assign(true, 'abc'); console.log(res1);
console.log(typeof res1); console.log(res1 instanceof Boolean);
const res2 = Object.assign('abc', true); console.log(res2);
console.log(typeof res2); console.log(res2 instanceof String);
const res3 = Object.assign(10, 'a'); console.log(res3);
console.log(typeof res3); console.log(res3 instanceof Number);
|
异常会打断后续拷贝任务
1 2 3 4 5
| const targetObj = Object.defineProperty({}, "foo", { value: 1, writable: false }); Object.assign(targetObj, {bar: 2}, {foo2: 3, foo: 3, foo3: 3}, {baz: 4});
|
注意这个异常是在拷贝第二个源对象的第二个属性时发生的。
拷贝访问器
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| const o = { foo: 1, get bar() { return 2; }, [Symbol('foo')]: 1 }; let copy1 = Object.assign({}, o); console.log('assign',copy1);
|