今回は分割代入をやるよ!
2015 年に標準化された、 JavaScript の比較的新しい仕様として、
「分割代入」というものがあります。
覚えておくと割と便利なのですが、あまり使われていない気がするので、
今回はこの、ちょっと便利な分割代入をご紹介しましょう。
最初に、対応しているブラウザ確認
分割代入は新しめの仕様なので、各ブラウザが対応しているかどうかを確認してみましょう。
いつもの Can I use で調べてみると…
IE 以外の主要ブラウザでは対応されていますね!
最悪、IE でも使いたいんだけどって話になれば、そのあたり babel とか使えば
IE でも読めるようにうまく変換してくれるからいいですね。
分割代入!基本の使い方
配列
さて、分割代入の具体的な話に入っていきます。
分割代入は一言で言えば、
配列やオブジェクトを変数に代入するときに、それをバラして入れてくれるという機能です。
例えば、分割代入なしで書くと
const ary = [3, 5]; const a = ary[0]; // 3 const b = ary[1]; // 5
こんな感じの処理。
これは、まず ary 変数に [3, 5]
の配列が代入されますよね。
(const は変数定義ですね)
で、配列の 0 番目、 1 番目をそれぞれ a, b の変数に代入している、という流れになります。
で、 a には 3 が、b には 5 が代入されますね。
これを分割代入を使って書くと…
const ary = [3, 5]; const [a, b] = ary; // a = 3 // b = 5
なんと!定義側にも配列みたいな [a, b]
が出てきましたね!
こんな感じで変数定義側に書くことで、代入する配列 ary にある、
位置が対応する値が a, b に直接入っていくのですね。
対応する形であればよいので、こんなこともできます。
const ary = [3, [6, 9]]; const [a, [b, c]] = ary; // a = 3 // b = 6 // c = 9
入れ子になっている配列についても、うまいこと展開してやってくれます。
オブジェクト
この分割代入、オブジェクトでも同じように使うことができます。
const obj = {a: 3, b: 6}; const {a, b} = obj; // a = 3 // b = 6
配列の場合は変数を書く場所を、配列の値の場所を合わせましたが、
オブジェクトの場合は、代入したいプロパティと名前を合わせます。
const obj = {a: 3, b: 6}; const {b, a} = obj; // a = 3 // b = 6
つまり、こういうことをしたら、配列の場合は値が入れ替わって入ってしまいますが、
オブジェクトの場合は名前が一致しているところに値を入れるので、
先ほどと同じ結果となる、ということですね。
ちなみに、配列の方ではできないのですが、
オブジェクトのほうはデフォルト値の設定ができます。
const obj = {a: 3, b: 6}; const {a = 10, c = 10} = obj; // a = 3 // c = 10 (c は obj のプロパティとして存在しないので、デフォルト値が使用される)
便利な使い方
正規表現での解析結果からの値の取り出し
JavaScript では正規表現にマッチした結果を配列として返してきてくれますよね。
const parsedURL = /^(\w+)\:\/\/([^\/]+)\/(.*)$/.exec(’https://example.com/path’); const [, protocol, host, path] = parsedURL;
parsedURL には [’https://example.com/path’, ’https’, ’example.com’, ’path’]
か入ってきますから、
これらを一つずつ変数代入するよりは、こんな感じでひとまとめにしてしてしまった方がスマートですよね。
値の入れ替え
(最近ではあまりないですが)例えば、変数 a と b の値を入れ替えるときは
let swap = a; let a = b; let b = swap;
こんな感じで、仮置きの変数を用意して実施しますよね?
でも、今回の分割代入を使うと
[a, b] = [b, a]
それぞれの位置の値を代入してくれるので、こんな感じで一行で書いてしまうこともできるのですね!
そんなに使う頻度はないですが、覚えておくと面白いタイプの小ネタです。
関数の引数を展開する
正直今回これを書きたかったがためにこの記事を書いてるくらいな、
みんなに知ってもらいたい便利な書き方。
オブジェクトは
const {b, a} = obj;
みたいな感じで展開すると、同じ名前のプロパティを変数に展開してくれると書きましたが、
これは関数の引数のところで同じように使えて、
// 引数受け取りのところでオブジェクトを展開 const sum = function({a, b}) { return a + b; } const obj = {a: 3, b: 4}; sum(obj); // 7 が返ってくる
こんなことができます。
これの何が便利って、ライブラリとかを使ってると、
一つのオブジェクトにいろいろなプロパティが格納されて一つになっていることがよくありますが、
- 関数を使う側はそのオブジェクトからプロパティを取り出さずそのまま渡せる
- 関数側は、オブジェクト内の不必要なプロパティは触ることなく処理ができる
ということなんですね。
もし、まだ使ったことがなければ、
実際に使ってみてもらったら、その便利さに驚くこと間違いなしです。
反復処理の変数も展開する
関数の引数と同じように
const ary = [ {name: ’hoge’, age: 10}, {name: ’fuga’, age: 12}, ]; for ({name} of ary) { console.log(name); // hoge fuga }
こんな感じで使えば、変数を展開した状態でループの中で使えます。
…が、関数の引数ほどの便利性は無いかな…
変数名の変更
ここからは多分使わない、というか可読性が落ちるので使いどころを考えてもらう必要があるネタです。
私は一度も使ったことないですが、一応こんなこともできますよというお話。
const obj = {a: 3, b: 6}; const {a: anotherName} = obj; console.log(anotherName); // 3
こんな感じで、元々のオブジェクト名の後ろに、コロンと別名を記載しておくことで、
別名の方を変数名として値を代入してくれます。
今回の例だと、元のプロパティ名である a の変数は作成されないのでご注意。
先ほどの関数の引数のところで展開する技と組み合わせると、
関数の中に、好きな名前で変数を作ることができます…
が、大抵プロパティ名で事足りるので、やっぱりほぼ使わないかな。
デフォルト関数
オブジェクトの分割代入ではデフォルト値を設定できるという話を最初の方にしました。
あのデフォルト値なのですが、本当は単純な値だけでなく、関数も指定できてしまうのです。
const obj = {a: 3, b: 6}; const def = function() { return 10; } const {c = def()} = obj; console.log(c); // 10
できます。できますが…
こういう訳の分からないことをし始めると、黒魔術に入門してしまうのでやめましょう。
ちなみに、一応補足しておくと、
デフォルト値の設定時点で () をつけていますが、
今回の場合で言えば a プロパティを参照するなどの、デフォルト値が使用されない場合には
この関数は実行されません。
…ということは、プロパティが設定されているときのみ実行される関数なんかかけそうですね。
const obj = {a: 3, b: 6}; const {c = (() => console.log(’c は定義されてないよ!’))()} = obj;
読む人からしたら、えげつないのでやめてくださいね。
まとめ
分割代入の可能性を色々と感じていただけたかなと思います。
最後のはネタとしてしか使えないですが、
関数の引数で分割代入は本当に便利なので皆さん使ってみてくださいね!