タグ別アーカイブ: ES6

ES6の新機能を学ぶ3 ~スプレッドオペレータと分割代入~

※この記事のJavascriptコードはGoogle Chrome 50.0.2661.102で動作確認しています。

少し間が空いてしまいましたが、「ES6の新機能を学ぶ」第3回をお届けします。

今回はスプレッドオペレータと分割代入という機能について解説します。

スプレッドオペレータ(Spread operator)

前回の投稿で解説したレストパラメータは、複数の引数を関数側で配列としてまとめて受け取るものでした。

スプレッドオペレータはこれとは逆に、配列を複数の引数に展開する機能です。

たとえば以下のような複数の引数を受け取る関数があるとします。

function foo(a, b, c){
  return a + b + c;
}

ES5まではこのような関数に配列を引数として与えたい場合、applyメソッドを利用して以下のように記述していました。

var arr = [1, 2, 3];

foo.apply(null, arr); // 6

ES6ではスプレッドオペレータを利用することで、以下のように簡潔な記述が可能になりました。
使い方は、配列変数の前にスプレッド演算子「…」を付けるだけです。

var arr = [1, 2, 3];

foo(...arr); // 6

ES5では、配列の連結にconcatメソッドを利用する場面があったかと思いますが、ES6からはスプレッドオペレータを利用することで、concatメソッドを使わずにシンプルな記述ができるようになりました。

//ES5の場合
var arr0 = [0, 1];

var arr1 = arr0.concat([2, 3, 4]);

console.log(arr1); // [0, 1, 2, 3, 4]
//ES6の場合
var arr0 = [0, 1];

var arr1 = [...arr0, 2, 3, 4];

console.log(arr1); // [0, 1, 2, 3, 4]

pushでも同様にスプレッドオペレータを利用できます。

//ES5の場合
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];

Array.prototype.push.apply(arr1, arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]
//ES6の場合
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];

arr1.push(...arr2);

console.log(arr1); // [0, 1, 2, 3, 4, 5]

分割代入(Destructuring assignment)

分割代入構文は、配列ないしオブジェクトから、複数の変数に値を代入できる式です。

//配列の場合
var [firstName, lastName] = ['太郎', '山田'];

console.log(`${lastName} ${firstName}`); //山田 太郎

//姓のみ取得
var [, lastName] = ['太郎', '山田'];

console.log(lastName); //山田

分割代入とレストパラメータを組み合わせて利用することも可能です。

var [year, ...monthDay] = [2016, 6, 9];

console.log(monthDay); // [6, 9]

配列だけでなくオブジェクトの分割代入も可能です。

//オブジェクトの場合
var {firstName: fName, lastName: lName} = {firstName: '太郎', lastName: '山田'};

console.log(`${lName} ${fName}`); //山田 太郎

//プロパティ名の省略も可能(ただし変数名とプロパティ名を一致させる必要あり)
var {firstName, lastName} = {firstName: '太郎', lastName: '山田'};

console.log(`${lastName} ${firstName}`); //山田 太郎

//デフォルト値の指定が可能
var {page = 0, count = 20} = {page:2};

console.log(`page => ${page}, count => ${count}`); //page => 2, count => 20

//ネストしたオブジェクトからの値抽出も可能。
var {parent: {child: { num: num } } } = {parent: {child: {num: 12} } };

console.log(num); // 12

関数の引数や、戻り値の受け取りでも分割代入の利用可能です。

以下のように関数の仮引数をオブジェクトリテラルの様に記述します。

function proc({first, second}){
  console.log(`first => ${first}, second => ${second}`);
}

var obj = {first: 1, second: 2};

proc(obj); // first => 1, second => 2

さらにデフォルトパラメータを設定することでES5の以下のような引数にデフォルト値を入れるためのコードをシンプルに書き換えることが可能です。

//ES5の場合

function proc(first, second){

  if (!first){
    first = 0;
  }

  if (!second){
    second = 0;
  }

  console.log(`first => ${first}, second => ${second}`);
}

proc(); // first => 0, second => 0
//ES6の場合

function proc({first = 0, second = 0} = {}){
  console.log(`first => ${first}, second => ${second}`);
}

proc(); // first => 0, second => 0

これを応用して以下のように特定の引数にだけ値を指定することもできます。

//引数firstへの値付与を省略して、secondのみに値を与える

function proc({first = 0, second = 0} = {}){
  console.log(`first => ${first}, second => ${second}`);
}

proc({second: 2}); // first => 0, second => 2

関数の戻り値を配列にし、受け取り側に分割代入構文を用いることで、多値返却を実現できます。

function multipleReturn(){
  return [1, 2, 3];
}

var [first, second, third] = multipleReturn();

console.log(`first => ${first}, second => ${second}, third => ${third}`); // first => 1, second => 2, third => 3

//不要な戻り値を無視することも可能です。
var [one, , three] = multipleReturn();

console.log(`one => ${one}, three => ${three}`); // one => 1, three => 3

以上の様に分割代入構文は、ES5では複数行必要であった内容を1行でシンプルに書ける強力な機能です。