スプレッド構文を使うと、関数呼び出しでは 0 個以上の引数として、Array リテラルでは 0 個以上の要素として、Object リテラルでは 0 個以上の key-value のペアとして、Array や String などの iterable オブジェクトをその場で展開します。

構文

関数呼び出し

myFunction(...iterableObj);

Array リテラル

[...iterableObj, '4', 'five', 6];

Object リテラル(ECMAScript 2018 の新機能)

let objClone = { ...obj };

関数呼び出しで使う

apply を置き換える

Array の要素を引数にして関数を呼び出すには Function.prototype.apply を使うのが一般的です。

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction.apply(null, args);

スプレッド構文を使うと、上のコードは次のように書けます。

function myFunction(x, y, z) { }
var args = [0, 1, 2];
myFunction(...args);

スプレッド構文は、引数の何番目でも使えます。また、複数回使えます。

function myFunction(v, w, x, y, z) { }
var args = [0, 1];
myFunction(-1, ...args, 2, ...[3]);

new 演算子と併用する

コンストラクタを new 演算子で呼ぶとき、 引数リストを Array で指定するために apply を使うことはできません。Function.prototype.apply はコンストラクタを関数として呼び出してしまうからです。

スプレッド構文を使えば、Array の要素をコンストラクタの引数として簡単に指定できます。

var dateFields = [1970, 0, 1];  // 1 Jan 1970
var d = new Date(...dateFields);

スプレッド構文を使わずに同じ結果を得るには、専用の関数を使う間接的な手段を取らざるをえません。

function applyAndNew(constructor, args) {
   function partial () {
      return constructor.apply(this, args);
   };
   if (typeof constructor.prototype === "object") {
     partial.prototype = Object.create(constructor.prototype);
   }
   return partial;
}


function myConstructor () {
   console.log("arguments.length: " + arguments.length);
   console.log(arguments);
   this.prop1="val1";
   this.prop2="val2";
};

var myArguments = ["hi", "how", "are", "you", "mr", null];
var myConstructorWithArguments = applyAndNew(myConstructor, myArguments);

console.log(new myConstructorWithArguments);
// (internal log of myConstructor):           arguments.length: 6
// (internal log of myConstructor):           ["hi", "how", "are", "you", "mr", null]
// (log of "new myConstructorWithArguments"): {prop1: "val1", prop2: "val2"}

Array リテラルで使う

より強力な配列リテラル

Array リテラルでスプレッド構文を使うと、すでにある Array を一部とする新しい配列を簡単に作れます。スプレッド構文を使わない場合、Array リテラルだけでは不十分で、pushspliceconcat などを使うコードを書かなければなりません。

var parts = ['shoulders', 'knees']; 
var lyrics = ['head', ...parts, 'and', 'toes']; 
// ["head", "shoulders", "knees", "and", "toes"]

関数の引数と同様に、... は Array リテラルのどこでも、何回でも使えます。

Array を複製する

var arr = [1, 2, 3];
var arr2 = [...arr]; // arr.slice() のような動きです
arr2.push(4); 

// arr2 は [1, 2, 3, 4] になります
// arr は変更されません

注意:コピーは 1 段階の深さで行われます。そのため、次の例のような多次元配列のようなオブジェクトをコピーする場合には適さないでしょう。Object.assign() についても同じことが言えます。

var a = [[1], [2], [3]];
var b = [...a];
b.shift().shift(); // 1
// a は影響を受けています: [[], [2], [3]]

Array を連結する

Array の連結には Array.concat がよく使われます。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// arr1 の後ろに arr2 を連結した新しい配列をつくる
arr1 = arr1.concat(arr2);

スプレッド構文を使うと、次のように書けます。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr1, ...arr2];

Array.unshift は、既存の配列の先頭に配列を挿入するためによく使われます。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
// Prepend all items from arr2 onto arr1
Array.prototype.unshift.apply(arr1, arr2) // arr1 is now [3, 4, 5, 0, 1, 2]

スプレッド構文を使うと、次のように書けます(ただし、この記述だと新しい配列を生成して arr1 に代入しています。Array.unshift と異なり、元の arr1 に追加していません)。

var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1 = [...arr2, ...arr1]; // arr1 is now [3, 4, 5, 0, 1, 2]

Object リテラルで使う

Rest/Spread Properties for ECMAScript proposal (stage 4) では、Object リテラルでのスプレッド構文が追加されています。スプレッド構文の対象となるオブジェクトの列挙可能なプロパティを、新しいオブジェクトにコピーします。

prototype を除いた浅いコピーの作成や、マージしたオブジェクトの作成が Object.assign() を使うよりも短いコードで書けます。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

Object.assign() は setters をトリガーしますが、スプレッド構文はトリガーできません。

スプレッド構文は Object.assign() 関数を置き換えたり模倣することはできません。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };
const merge = ( ...objects ) => ( { ...objects } );

var mergedObj = merge ( obj1, obj2);
// Object { 0: { foo: 'bar', x: 42 }, 1: { foo: 'baz', y: 13 } }

var mergedObj = merge ( {}, obj1, obj2);
// Object { 0: {}, 1: { foo: 'bar', x: 42 }, 2: { foo: 'baz', y: 13 } }

上記の例でスプレッド演算子は期待通りに動きません。レストパラメーターは配列で、オブジェクトリテラルに配列として展開されます。

iterable オブジェクトだけに使えます

Object リテラルで使う場合を除き、スプレッド構文は iterable オブジェクトだけに使えます。iterable でないオブジェクトでは、TypeError 例外となります。

var obj = {'key1': 'value1'};
var array = [...obj]; // TypeError: obj is not iterable

大量の値を展開する場合

JavaScript エンジンには、引数の個数に上限があります。関数呼び出しでのスプレッド構文では、引数の個数がその上限を超えてしまう可能性に留意してください。詳細は apply() のページを参照してください。

レスト構文(レストパラメータ)

レスト構文はスプレッド構文と全く同じ見た目をしていますが、Array や Object の分割代入に使われます。こちらはスプレッド構文とは逆の働きといえます: スプレッド構文が要素を展開するのに対して、レスト構文は複数の要素を集約して 1 つのオブジェクトにします。レスト構文 のページを参照してください。

仕様

仕様 ステータス コメント
ECMAScript 2015 (6th Edition, ECMA-262) 標準 配列初期化子, 引数リスト のセクションで定義されました。
ECMAScript 2018 (ECMA-262) 標準 オブジェクト初期化子で定義されました。
ECMAScript Latest Draft (ECMA-262) ドラフト 変更はありません。
ECMAScript Latest Draft (ECMA-262) ドラフト 変更はありません。

ブラウザー実装状況

Update compatibility data on GitHub
デスクトップモバイルサーバー
ChromeEdgeFirefoxInternet ExplorerOperaSafariAndroid webviewAndroid 版 ChromeEdge MobileAndroid 版 FirefoxAndroid 版 OperaiOS 版 SafariSamsung InternetNode.js
Spread in array literalsChrome 完全対応 46Edge 完全対応 12Firefox 完全対応 16IE 未対応 なしOpera 完全対応 37Safari 完全対応 8WebView Android 完全対応 46Chrome Android 完全対応 46Edge Mobile 完全対応 12Firefox Android 完全対応 16Opera Android 完全対応 37Safari iOS 完全対応 8Samsung Internet Android 完全対応 5.0nodejs 完全対応 5.0.0
完全対応 5.0.0
完全対応 4.0.0
無効
無効 From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in function callsChrome 完全対応 46Edge 完全対応 12Firefox 完全対応 27IE 未対応 なしOpera 完全対応 37Safari 完全対応 8WebView Android 完全対応 46Chrome Android 完全対応 46Edge Mobile 完全対応 12Firefox Android 完全対応 27Opera Android 完全対応 37Safari iOS 完全対応 8Samsung Internet Android 完全対応 5.0nodejs 完全対応 5.0.0
完全対応 5.0.0
完全対応 4.0.0
無効
無効 From version 4.0.0: this feature is behind the --harmony runtime flag.
Spread in destructuringChrome 完全対応 49Edge 未対応 なしFirefox 完全対応 34IE 未対応 なしOpera 完全対応 37Safari ? WebView Android 完全対応 49Chrome Android 完全対応 49Edge Mobile 未対応 なしFirefox Android 完全対応 34Opera Android 完全対応 37Safari iOS ? Samsung Internet Android 完全対応 5.0nodejs 完全対応 あり
Spread in object literals
実験的
Chrome 完全対応 60Edge 未対応 なしFirefox 完全対応 55IE 未対応 なしOpera ? Safari 未対応 なしWebView Android 完全対応 60Chrome Android 完全対応 60Edge Mobile 未対応 なしFirefox Android 完全対応 55Opera Android ? Safari iOS 未対応 なしSamsung Internet Android 未対応 なしnodejs 完全対応 8.3.0
完全対応 8.3.0
完全対応 8.0.0
無効
無効 From version 8.0.0: this feature is behind the --harmony runtime flag.

凡例

完全対応  
完全対応
未対応  
未対応
実装状況不明  
実装状況不明
実験的。動作が変更される可能性があります。
実験的。動作が変更される可能性があります。
ユーザーが明示的にこの機能を有効にしなければなりません。
ユーザーが明示的にこの機能を有効にしなければなりません。

関連情報

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

このページの貢献者: segayuu, kei-itof
最終更新者: segayuu,