현재 번역은 완벽하지 않습니다. 한국어로 문서 번역에 동참해주세요.
Object.assign()
메서드는 하나 이상의 소스 오브젝트로 부터 타켓 오브젝트로 프로퍼티들을 복사하는데 사용됩니다.
문법
Object.assign(target, ...sources)
인자
target
- 타켓 오브젝트
sources
- 하나 이상의 소스 오브젝트
리턴값
타겟 오브젝트
Description
소스 프로퍼티와 동일한 프로퍼티의 키를 가진 타켓 오브젝트의 프로퍼티들은 소스 오브젝트의 프로퍼티로 덮어쓰기 될 것입니다.
Object.assign()
메소드는 enumerable한 소스 오브젝트의 프로퍼티들만 타켓 오브젝트로 복사합니다. 이 메소드는 소스 오브젝트 대상으로 게터를 호출하고, 타켓 오브젝트 대상으로 세터를 호출합니다.
이 점이 머지 소스가 게터 메소드들을 포함하고 있다면 이 메소드를 새로운 프로퍼티를 포로토타입으로 머지하기 위해 사용하는데 부적합게 만들지도 모릅니다. 프로토타입으로 프로퍼티 정의를 복사하기 위해서는
그러므로 소스 오브젝트의 프로퍼티를 그냥 복사하거나 새로운 프로퍼티를 생성하면서 타켓 오브젝트의 프로퍼티를 할당해나갑니다.Object.getOwnPropertyDescriptor()
와 Object.defineProperty()
을 사용하시기 바랍니다.
String
과 Symbol
프로퍼티 둘다 복사됩니다.
프로퍼티가 쓰기 불가 등과 같이 만약 에러가 발생했을 때는, TypeError
가 발생하고 타겟 오브젝트에는 변화가 없을 것입니다.
Object.assign() 메소드는
null
이나 undefined
는 반환하지 않으니 주의하세요.
예제
객체 복제
var obj = { a: 1 }; var copy = Object.assign({}, obj); console.log(copy); // { a: 1 }
깊은 복제에 대한 주의사항
For deep cloning, we need to use other alternatives. This is because Object.assign()
copies the property reference when the property being assigned is an object.
function test() { let a = { b: {c:4} , d: { e: {f:1}} } let g = Object.assign({},a) let h = JSON.parse(JSON.stringify(a)); console.log(g.d) // { e: { f: 1 } } g.d.e = 32 console.log('g.d.e set to 32.') // g.d.e set to 32. console.log(g) // { b: { c: 4 }, d: { e: 32 } } console.log(a) // { b: { c: 4 }, d: { e: 32 } } console.log(h) // { b: { c: 4 }, d: { e: { f: 1 } } } h.d.e = 54 console.log('h.d.e set to 54.') // h.d.e set to 54. console.log(g) // { b: { c: 4 }, d: { e: 32 } } console.log(a) // { b: { c: 4 }, d: { e: 32 } } console.log(h) // { b: { c: 4 }, d: { e: 54 } } } test();
객체 병합
var o1 = { a: 1 }; var o2 = { b: 2 }; var o3 = { c: 3 }; var obj = Object.assign(o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 } console.log(o1); // { a: 1, b: 2, c: 3 }, target object itself is changed.
같은 프로퍼티를 가지는 객체 병합
var o1 = { a: 1, b: 1, c: 1 }; var o2 = { b: 2, c: 2 }; var o3 = { c: 3 }; var obj = Object.assign({}, o1, o2, o3); console.log(obj); // { a: 1, b: 2, c: 3 }
The properties are overwritten by other objects that have the same properties later in the parameters order.
심볼 타입 프로퍼티 복사
var o1 = { a: 1 }; var o2 = { [Symbol('foo')]: 2 }; var obj = Object.assign({}, o1, o2); console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox) Object.getOwnPropertySymbols(obj); // [Symbol(foo)]
Properties on the prototype chain and non-enumerable properties cannot be copied
var obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain. bar: { value: 2 // bar is a non-enumerable property. }, baz: { value: 3, enumerable: true // baz is an own enumerable property. } }); var copy = Object.assign({}, obj); console.log(copy); // { baz: 3 }
Primitives will be wrapped to objects
var v1 = 'abc'; var v2 = true; var v3 = 10; var v4 = Symbol('foo'); var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); // Primitives will be wrapped, null and undefined will be ignored. // Note, only string wrappers can have own enumerable properties. console.log(obj); // { "0": "a", "1": "b", "2": "c" }
Exceptions will interrupt the ongoing copying task
var target = Object.defineProperty({}, 'foo', { value: 1, writable: false }); // target.foo is a read-only property Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 }); // TypeError: "foo" is read-only // The Exception is thrown when assigning target.foo console.log(target.bar); // 2, the first source was copied successfully. console.log(target.foo2); // 3, the first property of the second source was copied successfully. console.log(target.foo); // 1, exception is thrown here. console.log(target.foo3); // undefined, assign method has finished, foo3 will not be copied. console.log(target.baz); // undefined, the third source will not be copied either.
Copying accessors
var obj = { foo: 1, get bar() { return 2; } }; var copy = Object.assign({}, obj); console.log(copy); // { foo: 1, bar: 2 }, the value of copy.bar is obj.bar's getter's return value. // This is an assign function that copies full descriptors function completeAssign(target, ...sources) { sources.forEach(source => { let descriptors = Object.keys(source).reduce((descriptors, key) => { descriptors[key] = Object.getOwnPropertyDescriptor(source, key); return descriptors; }, {}); // by default, Object.assign copies enumerable Symbols too Object.getOwnPropertySymbols(source).forEach(sym => { let descriptor = Object.getOwnPropertyDescriptor(source, sym); if (descriptor.enumerable) { descriptors[sym] = descriptor; } }); Object.defineProperties(target, descriptors); }); return target; } var copy = completeAssign({}, obj); console.log(copy); // { foo:1, get bar() { return 2 } }
Polyfill
This polyfill doesn't support symbol properties, since ES5 doesn't have symbols anyway:
if (typeof Object.assign != 'function') { (function () { Object.assign = function (target) { 'use strict'; // We must check against these specific cases. if (target === undefined || target === null) { throw new TypeError('Cannot convert undefined or null to object'); } var output = Object(target); for (var index = 1; index < arguments.length; index++) { var source = arguments[index]; if (source !== undefined && source !== null) { for (var nextKey in source) { if (source.hasOwnProperty(nextKey)) { output[nextKey] = source[nextKey]; } } } } return output; }; })(); }
Specifications
Specification | Status | Comment |
---|---|---|
ECMAScript 2015 (6th Edition, ECMA-262) The definition of 'Object.assign' in that specification. |
Standard | Initial definition. |
ECMAScript 2017 Draft (ECMA-262) The definition of 'Object.assign' in that specification. |
Draft |
Browser compatibility
Feature | Chrome | Firefox (Gecko) | Internet Explorer | Edge | Opera | Safari |
---|---|---|---|---|---|---|
Basic support | 45 | 34 (34) | No support | (Yes) | 32 | 9 |
Feature | Android | Chrome for Android | Firefox Mobile (Gecko) | IE Mobile | Opera Mobile | Safari Mobile |
---|---|---|---|---|---|---|
Basic support | No support | 45 | 34.0 (34) | No support | No support | (Yes) |