現代的JavaScriptおれおれアドベントカレンダー2017 – 14日目
概要
オブジェクトとかでまとまってもらえる情報を、最初からバラバラにしちゃうやつです。
const data = { age: 99, id: id, name: 'Alice', }; const { name, age } = data; console.log(name); // => "Alice" console.log(age); // => 99
配列もばらせます。別稿参照。
使い方
左辺ににょろ括弧 {
… }
で括って、欲しいプロパティの名前を書きます。
const data = { id: 123, name: 'Alice' }; const { id, age } = data; console.log(id); // => 123 console.log(age); // => undefined
右辺のオブジェクトから合致する名前のプロパティの値を代入します。 (id
)
右辺にないもの (age
) を指定すると undefined
になり、また右辺にあるもの (name
) を必ずしも左辺に用意する必要はありません。
かんたん、かんたん。
初期値
=
で、値が undefined
だった場合の初期値を設定できます。
const data = { id: 123, name: undefined }; const { name = 'Anonymous', age = 0 } = data; console.log(name, age); // => "Anonymous", 0
null
は普通に代入されます。
入れ子
入れ子になった情報を取り出すこともできます。その場合、途中のプロパティは値が取得されません。
const data = { detail: { phone: { number: '0120-000-000', type: 'free', }, }, }; const { detail: { phone: { number, type } } } = data; console.log(number); // => "0120-000-000" console.log(type); // => "free" console.log(detail); // Exception: ReferenceError: detail is not defined
異なる名前で
APIで情報を取ってきたは良いけどなんかその命名違うんだよなーみたいな場合にも使えます。
{ original: renamed }
のようにして original
を renamed
へ代入できます。
const data = { updated_at: '2017-12-14 00:00' }; const { updated_at: updatedAt } = data; console.log(updatedAt); // => "2017-12-14 00:00"
全部乗せ
初期値、入れ子、異名を全部組み合わせてもよろしい。
const data = { detail: { updated_at: '2017-12-14 00:00' } }; const { detail: { user_name: name = 'Anonymous', updated_at: updatedAt = 'NA', } } = data; console.log(name); // => "Anonymous" (default value) console.log(updatedAt); // => "2017-12-14 00:00"
改行してもなお読みづらい感じはするね。うん、わかるよその気持ち。
関数の仮引数で
最初はちょっとぎょっとするかもしれないけど、仮引数の括弧の中でも使えます。
function sayHello({ message, delay = 1000 }) { setTimeout(() => console.log(message), delay); } sayHello({ message: 'Hello World!' });
必要なオプションが一目瞭然で良いかも。数が少ない間はね。
オプションオブジェクト option
でざっくり受け取って、なんか中で処理を分けるとかすると良いかも?
function doGreatStuff(options) { doSomething(options); doAnything(options); doWhatever(options); } function doSomething({ foo }) {} function doAnything({ bar }) {} function doWhatever({ boo, hoge }) {}
その他
定義済み変数でSyntaxErrorになる
これはだめ。
const data = { foo: 'fufu' }; let foo; { foo } = data; // Exception: SyntaxError: expected expression, got '='
行頭の {
がブロックとみなされてしまうため。
括弧 (
… )
で括って式として判断させます。
const data = { foo: 'fufu' }; let foo; ({ foo } = data); console.log(foo); // => "fufu"
もちろん、普通にその場で変数宣言すれば問題ないです。
const data = { foo: 'fufu' }; const { foo } = data; console.log(foo); // => "fufu"
import
見た目は似てるけど違います。
import React, { Component } from 'react'; import { AppRegistry, Text, StyleSheet } from 'react-native';
雰囲気も似てるけど、動きも仕様も別物です。
destructuring assign
“destructure” は「破壊する」だそうです。あんまり一般的な語句ではないっぽい?
「分解代入」の方が意味的には適切なのかな。おれも分割代入って呼ぶけど。
デストラクタ destructor
じゃないです。コンストラクタの逆のやつ。
いや、まあこれはこれで欲しいことあるよね。いらない参照を明示的に切ったりとかイベント監視解除したりとかね。でも自動GCだからね。
参考
- ECMAScript® 2017 Language Specification
- 12.15.5 Destructuring Assignment … 最初の初期化
- 12.15.5.2 Runtime Semantics: DestructuringAssignmentEvaluation … 評価の様子(長くて読めてない……)
- 13.3.3 Destructuring Binding Patterns … 後から代入
- 14.1 Function Definitions
- 15.2.2 Imports … 似て非なる文法
- 分割代入 – JavaScript | MDN
- 分割代入、配列も画期的。(現代的JavaScriptおれおれアドベントカレンダー2017 – 15日目)
更新履歴
- 2017-12-15 importは違うぞと言われてアアアーッッ!となって削除しました。たしかにいろいろ違います、すみません。