JavaScriptは昔から存在するプログラミング言語なので、昔からの書き方とモダンな書き方が混在しています。
後方互換性が高い言語なので、昔からの書き方でも書けますが、新しい書き方の方がより効率的です。
今回の記事では特にスプレッド構文と分割代入に注目して、よりモダンな書き方を実現する方法を解説します。
スプレッド構文
例えば、以下のような関数を想定します。
この関数は3つの引数を取ります。
function sum(x, y, z) {
return x + y + z;
}
この関数に対して、以下の配列 ary
を引数として渡したいとします。
const ary = [2, 3, 4];
従来の書き方であれば、次のように引数を渡すでしょう。
少し冗長的で面倒に感じる方も多いと思います。
sum(ary[0], ary[1], ary[2]);
そこで使えるのが、スプレッド構文になります。
次のように、...
を使うことで、変数を展開して値を渡せます。
先程の配列のindexを一つずつ指定することなく、シンプルに引数として指定できます。
sum(...ary);
配列の合成に使う
スプレッド構文は変数を展開して、処理に渡せるという点がポイントになります。
上述までの例では、配列を引数として渡すケースのみでしたが、
これを使うと、次のように配列の合成にも使えます。
const ary1 = [1, 2, 3];
const ary2 = [1, 2, ...ary1];
console.log(ary2);
// [1, 2, 1, 2, 3]
また、同様の処理は concat
メソッドでも書けます。
concatは元の変数を変更しないので、受け取る形になってしまうのが注意点です。
const ary2 = [1, 2].concat(ary1);
配列をコピーする
スプレッド構文は、配列のコピーでも活躍します。
まず、スプレッド構文利用の前に、
JavaScriptでの変数が参照渡しとなる例を紹介します。
下の例では、変数から新たな変数を作成しています。
この場合、新しく作成した変数は、前の変数に与えた影響を受てしまいます。
これは参照渡しのため発生する副作用です。
const ary1 = [1, 2, 3];
const ary2 = ary1; // 新たな変数に代入(参照渡し)
// ary1にのみ変数を足す
ary1.push(4);
// ary2も影響を受ける
console.log(ary2);
// [1, 2, 3, 4]
このように変数をコピーすると、思わぬ変更が行われてしまう場合があります。
それを防ぐために、スプレッド構文が利用できます。
const ary1 = [1, 2, 3];
const ary2 = [...ary1]; // スプレッド構文で別変数を定義
// ary1だけ変数を足す
ary1.push(4);
// ary2は影響を受けない
console.log(ary2);
// [1, 2, 3]
オブジェクトでも利用できます
スプレッド構文は配列だけでなく、オブジェクトでも利用できます。
const obj = {
a: 'b',
c: 'd',
};
const obj2 = {...obj, ...{e: 'f'}};
console.log(obj2);
// {a: 'b', c: 'd', e: 'f'}
同じキー名があった場合、後で指定したオブジェクトが優先されるので注意してください。
以下の例では a
キーの値が上書きされています。
const obj1 = {
a: 'b',
c: 'd',
};
const obj2 = {
a: 1,
b: 2,
};
const obj3 = {...obj1, ...obj2, ...{e: 'f'}};
console.log(obj3);
// {a: 1, c: 'd', b: 2, e: 'f'}
分割代入
分割代入は、変数の値をシンプルに受け取れるようにする仕組みです。
こちらも配列、オブジェクトに対して利用できます。
例えば、以下の配列を、変数 a
/ b
/ c
の3つに分ける場合を想定します。
const ary = [1, 2, 3];
const a = ary[0];
const b = ary[1];
const c = ary[2];
この書き方を分割代入で書くと、次のようになります。とてもシンプルですね。
const [a, b, c] = ary;
オブジェクトでも同じです。
従来の場合は、次のようになるでしょう。
const obj = {
a: 'aaa',
b: 'bbb',
c: 'ccc',
};
const a = obj.a;
const b = obj.b;
const c = obj.c;
これを分割代入で書くと、次のようになります。
オブジェクトのキーと、変数名が一致している必要がありますので注意が必要です。
const { a, b, c } = obj;
キー名と変数名を分ける場合
キー名に対して、別の変数名で受け取る場合は、次のように書きます。
以下は a
キーの値を aa
という変数に。
b
キーの値を bb
という変数。
c
キーの値を cc
変数に入れるという内容です。
const { a: aa, b: bb, c: cc } = obj;
さらに、キーがなかった場合のデフォルト値も指定できます。
以下の場合、 d
は ddd
という値がデフォルト値になります。
const { a: aa, b: bb, c: cc, d = 'ddd' } = obj;
入れ子のオブジェクト
オブジェクトが入れ子になっていても、分割代入できます。
const obj = {
a: {
b: 'c',
},
aa: 'd',
}
const { a: { b }, aa } = obj;
console.log(b); // 'c'
console.log(aa); // 'd'
分割代入の使いどころ
分割代入は オブジェクト.キー名
で何度も書くのが面倒な時に使えます。
// 従来の書き方
const name = obj.name;
const age = obj.age;
// 分割代入
const { name, age } = obj;
良くあるのは、関数の結果を分割代入で受け取るものです。
// URLへリクエストした結果のステータス、エラー、ボディーを受け取る
const { status, error, body } = getContentXXXX(url);
Framework7での実例
最近Monacaでよく利用しているFramework7でも、分割代入が使われています。以下の部分です。
export default (props, { $f7, $on }) => {
// この中で処理を書く
});
これは従来の書き方であれば次のようになります。
この変数に入れ直す部分を省略できるのが、分割代入を利用するメリットになります。
export default function (props, params) => {
const $f7 = params.$f7;
const $on = params.$on;
// この中で処理を書く
});
まとめ
スプレッド構文も分割代入も、慣れてしまうと手放せない書き方になります。
コードを読む方も、慣れてしまえばとても分かりやすいでしょう。
ぜひ活用して、あなたのアプリ開発を効率化してください。