スプレッド構文を使うと、関数呼び出しでは 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 を一部とする新しい配列を簡単に作れます。

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

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

スプレッド構文を使わない場合、Array リテラルだけでは不十分で、pushspliceconcat などを使うコードを書かなければなりません。

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);
// [0, 1, 2, 3, 4, 5]

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

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

 

 

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 }

 

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) 標準 Defined in several sections of the specification: Array Initializer, Argument Lists
ECMAScript Latest Draft (ECMA-262) ドラフト No changes.
ECMAScript Latest Draft (ECMA-262) ドラフト Defined in Object Initializer

ブラウザ互換性

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.

凡例

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

関連情報

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

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