이 번역은 완료되지 않았습니다. 이 문서를 번역해 주세요.

Object.assign() 메서드는 열거할 수 있는 하나 이상의 출처 객체로부터 대상 객체로 속성을 복사할 때 사용합니다. 대상 객체를 반환합니다.

구문

Object.assign(target, ...sources)

매개변수

target
대상 객체.
sources
하나 이상의 출처 객체.

반환 값

대상 객체.

설명

소스 프로퍼티와 동일한 프로퍼티의 키를 가진 타켓 오브젝트의 프로퍼티들은 소스 오브젝트의 프로퍼티로 덮어쓰기 될 것입니다.

Object.assign() 메소드는 열거할 수 있는 소스 오브젝트의 프로퍼티들만 타켓 오브젝트로 복사합니다. 이 메소드는 소스 오브젝트 대상으로 게터를 호출하고, 타켓 오브젝트 대상으로 세터를 호출합니다.
따라서, 소스 오브젝트의 프로퍼티를 그냥 단순히 복사하거나, 새로운 프로퍼티를 생성하는 것이 아니라, 타켓 오브젝트의 프로퍼티를 게터와 세터를 이용하여 할당할 수도 있습니다. 먄약, 병합되는 소스 오브젝트가 게터를 포함하고 있다면, 새로운 프로퍼티를 타겟의 프로토타입에 병합하는 것은 알맞지 않을 것입니다. 열거가능성을 포함한 프로퍼티를  프로토타입으로 복사하기 위해서는 Object.getOwnPropertyDescriptor() 와  Object.defineProperty() 을 사용하시기 바랍니다.

String 과 Symbol 프로퍼티 둘 다 복사될 것입니다.

프로퍼티가 쓰기불가능(non-writable) 등과 같이 만약 에러가 발생할 수 있는 상황에서는,  TypeError 가 발생하고 타겟 오브젝트에는 변화가 없을 것입니다.

Object.assign() 메서드는 null 이나 undefined 는 반환하지 않으니 주의하세요.

예제

객체 복사하기

const obj = { a: 1 };
const copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }

깊은 복사에 대한 주의사항

Object.assign()은 속성의 값을 복사하므로 출처 속성값이 객체에 대한 참조면 참조를 복사합니다. 따라서 깊은 복사는 다른 방법을 사용해야 합니다.

function test() {
  'use strict';

  let obj1 = { a: 0 , b: { c: 0}};
  let obj2 = 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}}
  
  // Deep Clone
  obj1 = { a: 0 , b: { c: 0}};
  let obj3 = JSON.parse(JSON.stringify(obj1));
  obj1.a = 4;
  obj1.b.c = 4;
  console.log(JSON.stringify(obj3)); // { a: 0, b: { c: 0}}
}

test();

객체 병합하기

const o1 = { a: 1 };
const o2 = { b: 2 };
const o3 = { c: 3 };

const obj = Object.assign(o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }
console.log(o1);  // { a: 1, b: 2, c: 3 }, 대상 객체는 변화합니다.

같은 속성을 가지고 있는 객체 병합하기

const o1 = { a: 1, b: 1, c: 1 };
const o2 = { b: 2, c: 2 };
const o3 = { c: 3 };

const obj = Object.assign({}, o1, o2, o3);
console.log(obj); // { a: 1, b: 2, c: 3 }

같은 이름의 속성은 뒤쪽 인자 객체가 덮어 씁니다.

심볼형 속성 복사하기

const o1 = { a: 1 };
const o2 = { [Symbol('foo')]: 2 };

const obj = Object.assign({}, o1, o2);
console.log(obj); // { a : 1, [Symbol("foo")]: 2 } (cf. bug 1207182 on Firefox)
Object.getOwnPropertySymbols(obj); // [Symbol(foo)]

프로토타입 체인의 속성과 열거 불가능한 속성은 복사할 수 없음

const obj = Object.create({ foo: 1 }, { // foo는 변수 obj의 프로토타입 체인 위에 있습니다.
  bar: {
    value: 2  // 변수 bar는 열거 불가능한 속성입니다.
  }
  baz: {
    value: 3,
    enumerable: true  // 변수 baz는 그 자체도 열거 가능한 속성입니다.
  }
});

const copy = Object.assign({}, obj);
console.log(copy); // { baz: 3 }

원시 자료형은 객체로

var v1 = 'abc';
var v2 = true;
var v3 = 10;
var v4 = Symbol('foo');

var obj = Object.assign({}, v1, null, v2, undefined, v3, v4); 
// null과 undefined는 무시될 것입니다.
// String wrapper만이 enumerable 프로퍼티를 가지고 있음을 주의하세요.
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

예외로 인한 복사 중단

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, 첫 번째 소스 오브젝트는 성공적으로 복사되었습니다.
console.log(target.foo2); // 3, 두 번째 소스 프로젝트의 첫 번째 프로퍼티도 성공적으로 복사되었습니다.
console.log(target.foo);  // 1, 예외는 여기서 던져집니다.
console.log(target.foo3); // undefined, Object.assign() 메소드는 끝났습니다. 변수 foo3는 복사되지 않습니다.
console.log(target.baz);  // undefined, 세 번째 소스 오브젝트, 역시 복사되지 않습니다.

접근자 복사하기

var obj = {
  foo: 1,
  get bar() {
    return 2;
  }
};

var copy = Object.assign({}, obj); 
console.log(copy); 
// { foo: 1, bar: 2 }, copy.bar의 값은 obj.bar'의 게터가 리턴해주는 값입니다.

// 이것은 모든 descriptors를 복사하는 할당 함수입니다.
function completeAssign(target, ...sources) {
  sources.forEach(source => {
    let descriptors = Object.keys(source).reduce((descriptors, key) => {
      descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
      return descriptors;
    }, {});
    // 기본적으로, Object.assign는 열거할 수 있는 Symbol도 복사합니다.
    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 } }

폴리필

ES5엔 심볼이 없기 때문에 다음 폴리필은 심볼 속성을 지원하지 않습니다.

if (typeof Object.assign != 'function') {
  // Must be writable: true, enumerable: false, configurable: true
  Object.defineProperty(Object, "assign", {
    value: function assign(target, varArgs) { // .length of function is 2
      'use strict';
      if (target == null) { // TypeError if undefined or null
        throw new TypeError('Cannot convert undefined or null to object');
      }

      var to = Object(target);

      for (var index = 1; index < arguments.length; index++) {
        var nextSource = arguments[index];

        if (nextSource != null) { // Skip over if undefined or null
          for (var nextKey in nextSource) {
            // Avoid bugs when hasOwnProperty is shadowed
            if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {
              to[nextKey] = nextSource[nextKey];
            }
          }
        }
      }
      return to;
    },
    writable: true,
    configurable: true
  });
}

명세

Specification Status Comment
ECMAScript 2015 (6th Edition, ECMA-262)
The definition of 'Object.assign' in that specification.
Standard Initial definition.
ECMAScript Latest Draft (ECMA-262)
The definition of 'Object.assign' in that specification.
Draft  

브라우저 호환성

Update compatibility data on GitHub
DesktopMobileServer
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewChrome for AndroidEdge MobileFirefox for AndroidOpera for AndroidiOS SafariSamsung InternetNode.js
Basic supportChrome Full support 45Edge Full support YesFirefox Full support 34IE No support NoOpera Full support 32Safari Full support 9WebView Android No support NoChrome Android Full support 45Edge Mobile Full support YesFirefox Android Full support 34Opera Android No support NoSafari iOS Full support YesSamsung Internet Android Full support 5.0nodejs Full support 4.0.0

Legend

Full support  
Full support
No support  
No support

 

See also

문서 태그 및 공헌자

이 페이지의 공헌자: urty5656, LOG91, kikas, faker007, dale0713
최종 변경자: urty5656,