一つ以上の ソース オブジェクトから、直接所有で (own)  列挙可能な (enumerable) すべてのプロパティの値を、ターゲット オブジェクトへコピーします。戻り値はターゲット オブジェクトです。

構文

Object.assign(target, ...sources)

引数

target
ターゲットオブジェクト
sources
ソースオブジェクト

戻り値

ターゲットオブジェクト

説明

Object.assign()メソッドは、ソース オブジェクトから列挙可能 (enumerable)かつ直接所有 (own)のプロパティだけをターゲット オブジェクトにコピーします。この際、ソース オブジェクトには[[Get]]、ターゲット オブジェクトには[[Set]]を使いますので、getterとsetterを呼び出すことになります。これはプロパティの 代入 (assign)であり、プロパティをコピーしたり新しく定義をしたりするのとは違います。そのため、ソースにgetterが存在する場合、新しいプロパティをプロトタイプにマージする目的には不適切でしょう。プロパティ定義を 列挙可能 (enumerable) 属性も含めてプロトタイプの中にコピーするには、 このメソッドではなく Object.getOwnPropertyDescriptor()Object.defineProperty() を使うべきです。

StringSymbol 両方のプロパティがコピーされます。

エラーが発生した場合(例えばプロパティが書き込み不可)、 TypeError が発生し、ターゲット オブジェクトは変更されません。

Object.assign()はソースの値が nullundefined でも例外を投げないことに注意して下さい。

オブジェクトを複製する

var obj = { a: 1 };
var 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();

オブジェクトをマージする

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オブジェクト自身が変化する

同じプロパティがあるオブジェクトをマージする

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 }

同じプロパティをもつオブジェクトがあると、パラメータの順序があとになるオブジェクトのプロパティ値で上書きされます。

シンボル型プロパティをコピーする

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)]

プロトタイプチェーン上のプロパティや列挙不可能なプロパティはコピーされない

var obj = Object.create({ foo: 1 }, { // foo is on obj's prototype chain.
  bar: {
    value: 2  // barは列挙不可能なプロパティ
  },
  baz: {
    value: 3,
    enumerable: true  // bazは直接所有で列挙可能なプロパティ
  }
});

var 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 は無視される
// 注意)文字列をラップした時だけ、直接所有で列挙可能なプロパティが存在する
console.log(obj); // { "0": "a", "1": "b", "2": "c" }

例外で現在進行中のコピー処理が中断される

var target = Object.defineProperty({}, 'foo', {
  value: 1,
  writable: false
}); // target.fooはread-onlyなプロパティ

Object.assign(target, { bar: 2 }, { foo2: 3, foo: 3, foo3: 3 }, { baz: 4 });
// TypeError: "foo" is read-only
// target.fooに代入しようとすると、この例外が投げられる

console.log(target.bar);  // 2, 一番目のソースオブジェクトはコピーされている
console.log(target.foo2); // 3, 二番目のソースの最初のプロパティもコピーされている
console.log(target.foo);  // 1, ここで例外が投げられた
console.log(target.foo3); // undefined, 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のgetterの返り値です。

// 記述子を完全にコピーする代入関数
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 は列挙可能なシンボルもコピーします。
    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

このpolyfillはsymbolプロパティをサポートしません。そもそも ES5 には symbol がありませんし。

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
  });
}

仕様

仕様 策定状況 コメント
ECMAScript 2015 (6th Edition, ECMA-262)
Object.assign の定義
標準 Initial definition.
ECMAScript Latest Draft (ECMA-262)
Object.assign の定義
ドラフト  

ブラウザ実装状況

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOS 版 SafariSamsung InternetNode.js
基本対応Chrome 完全対応 45Edge 完全対応 ありFirefox 完全対応 34IE 未対応 なしOpera 完全対応 32Safari 完全対応 9WebView Android 未対応 なしChrome Android 完全対応 45Edge Mobile 完全対応 ありFirefox Android 完全対応 34Opera Android 未対応 なしSafari iOS 完全対応 ありSamsung Internet Android 完全対応 5.0nodejs 完全対応 4.0.0

凡例

完全対応  
完全対応
未対応  
未対応

関連情報

ドキュメントのタグと貢献者

このページの貢献者: FumioNonaka, woodmix, sgitmot, sapics, taiyaki32lp64, lv7777, saneyuki_s, shide55
最終更新者: FumioNonaka,