현재 번역은 완벽하지 않습니다. 한국어로 문서 번역에 동참해주세요.
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) |