Vuexでよく見る波括弧を使った引数の代入は、分割代入というJavaScriptの新しい構文だった

Vuex の action の第1引数で、 method({ commit }) といった、波括弧を使ったちょっと気持ち悪い記述を見かける。

実際に渡される context から context.commit を抽出しているんだろうと思って何となく使っていたが、正確にはどういう機能なのかと思って調べてみたのでメモ。

Vuex

とりあえず、Vuexのドキュメントを読んでみる。

vuex.vuejs.org

実際にはコードを少しシンプルにするために ES2015 の引数分割束縛(argument destructuring)がよく使われます

とあり、以下へのリンクが張られている。

github.com

ここでは「Destructuring」という名前で紹介されている。

MDN

VuexやVue.jsがどうこうではなく、シンプルにES6(ECMAScript 2015) で追加された仕様の模様。

JavaScriptの仕様であればMDNを検索すればいい、ということでMDN内を「Destructuring」で検索すると、「分割代入」という構文で引っかかった。

developer.mozilla.org

分割代入構文の使い方

基本的な使い方以外にも、規定値の設定などできたため、MDNから使いそうなものを抜粋。

基本的な使い方

代入の左辺が、代入元の変数からどの値を受け取るかを定義する。代入元として、配列またはオブジェクトを利用可能。

Pythonで、タプルやリストを複数の変数に代入するようなイメージ。

// 配列の場合、左辺を[]で囲む
const [a, b] = [1, 2];
console.log(a); // 1
console.log(b); // 2

// オブジェクトの場合、左辺を{}で囲む
const {x, y} = {x: 3, y: 4}
console.log(x); // 3
console.log(y); // 4

規定値の設定

左辺の変数設定時に 変数名 = 規定値 としておくことで、右辺の該当値が undefined の場合は規定値が使用される。

なお、右辺の値が null の場合、きちんと null が代入される。

// 配列の場合
const [a = 1, b = 2, c = 3] = [, undefined, null];
console.log(a); // 1
console.log(b); // 2
console.log(c); // null

// オブジェクトの場合
const {x = 3, y = 4, z = 5} = {x: undefined, z: null};
console.log(x); // 3
console.log(y); // 4
console.log(z); // null

残余部分への変数の代入

左辺の最後の変数の接頭辞として ... を付与すると、残りの右辺の変数がすべてその変数に設定される。

残余引数を利用している模様。

右辺の残りの変数の数にかかわらず、 ... を付与した変数は、配列の場合は配列、オブジェクトの場合はオブジェクトとなる。残りの変数が0であれば、空の配列またはプロパティのないオブジェクトとなる。

また、オブジェクトの場合、 ... を付与した変数と同じ名前のキーが右辺に存在しても、... を付与した変数のオブジェクトのプロパティとして設定された。

// 配列の場合
let a, b;
[a, ...b] = [1, 2, 3];
console.log(b); // Array [2, 3]
[a, ...b] = [1];
console.log(b); // Array []


// オブジェクトの場合
let x, y;
({x, ...y} = {x: 3, y: 4, z: 5}); // 丸括弧で囲まないとエラーとなる
console.log(y); // Object { y: 4, z: 5 }
({x, ...y} = {x: 3});
console.log(y); // Object {  }

異なる名前を持つ変数への代入

オブジェクトの場合、左辺を { 右辺の変数名: 代入する変数名 } とすることで、オブジェクトのプロパティとは異なる名前の変数に代入できる。

規定値も設定可能。

const {a: x, b: y, c: z = 3} = {a: 1, b: 2};
console.log(x); // 1
console.log(y); // 2
console.log(z); // 3

また、右辺の変数名として、変数を使用できる。ただし、変数名をそのまま書くとエラーとなるため、 [] で囲むことに注意。

const targetKey = 'a';
const {[targetKey]: x} = {a: 1};
console.log(x); // 1

余談

Vue.js でいうと、 v-for でも使える模様。ただし、公式ドキュメントには記載がなさそう。

Vue.jsのv-forで分割代入をする - Qiita

振り返り

JavaScript 引数 波括弧」や、「Vue 引数 気持ち悪い」で検索しても引っかからず、なかなか「分割代入」という名前にたどり着けなかった。

名前がわかったので検索すると、もう数年前にはブログやQiitaで記事になっている。

ES6の機能というと、 let, const やアロー関数、Class構文、スプレッド構文、テンプレート文字列、 Promise などを使うことが多く、意識から漏れていたんだろうなぁ。