Please note, this is a STATIC archive of website developer.mozilla.org from 03 Nov 2016, cach3.com does not collect or store any user information, there is no "phishing" involved.

Object.assign()

この記事は技術レビューを必要としています。ぜひご協力ください

この記事は編集レビューを必要としています。ぜひご協力ください

一つ以上の ソース オブジェクトから、直接所有で (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 }

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

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 };
var o2 = { [Symbol('foo')]: 2 };

var obj = Object.assign({}, o1, o2);
console.log(obj); // { a: 1, [Symbol("foo")]: 2 }

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

var obj = Object.create({ foo: 1 }, { // fooは継承されたプロパティ
  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,
  writeable: 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') {
  (function () {
    Object.assign = function (target) {
      'use strict';
      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 (Object.prototype.hasOwnProperty.call(source, nextKey)) {
              output[nextKey] = source[nextKey];
            }
          }
        }
      }
      return output;
    };
  })();
}

仕様

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

ブラウザ実装状況

機能 Chrome Firefox (Gecko) Internet Explorer Edge Opera Safari
基本サポート 45 34 (34) 未サポート (有) 32 9
機能 Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
基本サポート 未サポート 45 34.0 (34) 未サポート 未サポート (有)

関連情報

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

 このページの貢献者: sapics, taiyaki32p, lv7777, saneyuki_s, shide55
 最終更新者: sapics,