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.

Revision 1062046 of Object.assign()

  • リビジョンの URL スラグ: Web/JavaScript/Reference/Global_Objects/Object/assign
  • リビジョンのタイトル: Object.assign()
  • リビジョンの ID: 1062046
  • 作成日:
  • 作成者: taiyaki32p
  • 現行リビジョン? いいえ
  • コメント 訳文見直し、サンプル修正と翻訳、英語版に追従

このリビジョンの内容

{{JSRef}}

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

構文

Object.assign(target, ...sources)

引数

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

戻り値

ターゲットオブジェクト

説明

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

{{jsxref("String")}} と {{jsxref("Symbol")}} 両方のプロパティがコピーされます。

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

Object.assign()はソースの値が {{jsxref("null")}} や {{jsxref("undefined")}} でも例外を投げないことに注意して下さい。

オブジェクトを複製する

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

この{{Glossary("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;
    };
  })();
}

仕様

仕様 策定状況 コメント
{{SpecName('ES6', '#sec-object.assign', 'Object.assign')}} {{Spec2('ES6')}} Initial definition.
{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}} {{Spec2('ESDraft')}}  

ブラウザ実装状況

{{CompatibilityTable}}
機能 Chrome Firefox (Gecko) Internet Explorer Opera Safari
基本サポート {{CompatChrome("45")}} {{CompatGeckoDesktop("34")}} {{CompatNo}} {{CompatVersionUnknown}} {{CompatOpera("32")}} {{CompatSafari("9")}}
機能 Android Chrome for Android Firefox Mobile (Gecko) IE Mobile Opera Mobile Safari Mobile
基本サポート {{CompatNo}} {{CompatChrome("45")}} {{CompatGeckoMobile("34")}} {{CompatNo}} {{CompatNo}} {{CompatVersionUnknown}}

関連情報

このリビジョンのソースコード

<div>{{JSRef}}</div>

<p>一つ以上の ソース オブジェクトから、{{原語併記("直接所有で","own")}}&nbsp; {{原語併記("列挙可能な","enumerable")}} すべてのプロパティの値を、ターゲット オブジェクトへコピーします。戻り値はターゲット オブジェクトです。</p>

<h2 id="Syntax" name="Syntax">構文</h2>

<pre class="syntaxbox">
<code>Object.assign(<var>target</var>, ...<var>sources</var>)</code></pre>

<h3 id="Parameters" name="Parameters">引数</h3>

<dl>
 <dt><code>target</code></dt>
 <dd>ターゲットオブジェクト</dd>
 <dt><code>sources</code></dt>
 <dd>ソースオブジェクト</dd>
</dl>

<h3 id="Return_value" name="Return_value">戻り値</h3>

<p>ターゲットオブジェクト</p>

<h2 id="Description" name="Description">説明</h2>

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

<p>{{jsxref("String")}} と {{jsxref("Symbol")}} 両方のプロパティがコピーされます。</p>

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

<p><code>Object.assign()</code>はソースの値が {{jsxref("null")}} や {{jsxref("undefined")}} でも例外を投げないことに注意して下さい。</p>

<h2 id="Examples" name="Examples">例</h2>

<h3 id="Cloning_an_object" name="Cloning_an_object">オブジェクトを複製する</h3>

<pre class="brush: js">
var obj = { a: 1 };
var copy = Object.assign({}, obj);
console.log(copy); // { a: 1 }
</pre>

<h3 id="オブジェクトをマージする">オブジェクトをマージする</h3>

<pre class="brush: js">
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オブジェクト自身も変化する
</pre>

<h3 id="">シンボル型プロパティをコピーする</h3>

<pre class="brush: js">
var o1 = { a: 1 };
var o2 = { [Symbol('foo')]: 2 };

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

<h3 id="">プロトタイプチェーン上のプロパティや列挙不可能なプロパティはコピーされない</h3>

<pre class="brush: js">
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 }
</pre>

<h3 id="プリミティブ型はオブジェクトにラップされる">プリミティブ型はオブジェクトにラップされる</h3>

<pre class="brush: js">
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" }
</pre>

<h3 id="例外が現在進行中のコピータスクを中断する">例外で現在進行中のコピー処理が中断される</h3>

<pre class="brush: js">
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, 三番目のソースもコピーされない
</pre>

<h3 id="アクセサをコピーする">アクセサのコピー</h3>

<pre class="brush: js">
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) {
&nbsp; sources.forEach(source =&gt; {
&nbsp;&nbsp;&nbsp; let descriptors = Object.keys(source).reduce((descriptors, key) =&gt; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; descriptors[key] = Object.getOwnPropertyDescriptor(source, key);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return descriptors;
&nbsp;&nbsp;&nbsp; }, {});
&nbsp;&nbsp;&nbsp; // デフォルトで、Object.assign は列挙可能なシンボルもコピーします。
&nbsp;&nbsp;&nbsp; Object.getOwnPropertySymbols(source).forEach(sym =&gt; {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; let descriptor = Object.getOwnPropertyDescriptor(source, sym);
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if (descriptor.enumerable) {
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; descriptors[sym] = descriptor;
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }
&nbsp;&nbsp;&nbsp; });
&nbsp;&nbsp;&nbsp; Object.defineProperties(target, descriptors);
&nbsp; });
&nbsp; return target;
}

var copy = completeAssign({}, obj);
console.log(copy);
// { foo:1, get bar() { return 2 } }
</pre>

<h2 id="Polyfill" name="Polyfill">Polyfill</h2>

<p>この{{Glossary("Polyfill","polyfill")}}はsymbolプロパティをサポートしません。そもそも ES5 には symbol がありませんし。</p>

<pre class="brush: js">
if (typeof Object.assign != 'function') {
&nbsp; (function () {
&nbsp; &nbsp; Object.assign = function (target) {
&nbsp; &nbsp; &nbsp; 'use strict';
&nbsp; &nbsp; &nbsp; if (target === undefined || target === null) {
&nbsp; &nbsp; &nbsp; &nbsp; throw new TypeError('Cannot convert undefined or null to object');
&nbsp; &nbsp; &nbsp; }

&nbsp; &nbsp; &nbsp; var output = Object(target);
&nbsp; &nbsp; &nbsp; for (var index = 1; index &lt; arguments.length; index++) {
&nbsp; &nbsp; &nbsp; &nbsp; var source = arguments[index];
&nbsp; &nbsp; &nbsp; &nbsp; if (source !== undefined &amp;&amp; source !== null) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (var nextKey in source) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (Object.prototype.hasOwnProperty.call(source, nextKey)) {
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; output[nextKey] = source[nextKey];
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; }
&nbsp; &nbsp; &nbsp; return output;
&nbsp; &nbsp; };
&nbsp; })();
}
</pre>

<h2 id="Specifications" name="Specifications">仕様</h2>

<table class="standard-table">
 <tbody>
  <tr>
   <th scope="col">仕様</th>
   <th scope="col">策定状況</th>
   <th scope="col">コメント</th>
  </tr>
  <tr>
   <td>{{SpecName('ES6', '#sec-object.assign', 'Object.assign')}}</td>
   <td>{{Spec2('ES6')}}</td>
   <td>Initial definition.</td>
  </tr>
  <tr>
   <td>{{SpecName('ESDraft', '#sec-object.assign', 'Object.assign')}}</td>
   <td>{{Spec2('ESDraft')}}</td>
   <td>&nbsp;</td>
  </tr>
 </tbody>
</table>

<h2 id="Browser_compatibility" name="Browser_compatibility">ブラウザ実装状況</h2>

<div>{{CompatibilityTable}}</div>

<div id="compat-desktop">
<table class="compat-table">
 <tbody>
  <tr>
   <th>機能</th>
   <th>Chrome</th>
   <th>Firefox (Gecko)</th>
   <th>Internet Explorer</th>
   <th>Opera</th>
   <th>Safari</th>
  </tr>
  <tr>
   <td>基本サポート</td>
   <td>{{CompatChrome("45")}}</td>
   <td>{{CompatGeckoDesktop("34")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatVersionUnknown}}</td>
   <td>{{CompatOpera("32")}}</td>
   <td>{{CompatSafari("9")}}</td>
  </tr>
 </tbody>
</table>
</div>

<div id="compat-mobile">
<table class="compat-table">
 <tbody>
  <tr>
   <th>機能</th>
   <th>Android</th>
   <th>Chrome for Android</th>
   <th>Firefox Mobile (Gecko)</th>
   <th>IE Mobile</th>
   <th>Opera Mobile</th>
   <th>Safari Mobile</th>
  </tr>
  <tr>
   <td>基本サポート</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatChrome("45")}}</td>
   <td>{{CompatGeckoMobile("34")}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatNo}}</td>
   <td>{{CompatVersionUnknown}}</td>
  </tr>
 </tbody>
</table>
</div>

<h2 id="See_also" name="See_also">関連情報</h2>

<ul>
 <li>{{jsxref("Object.defineProperties()")}}</li>
 <li><a href="/ja/docs/Web/JavaScript/Enumerability_and_ownership_of_properties">JavaScriptガイド "Enumerability and ownership of properties"</a></li>
</ul>
このリビジョンへ戻す