現代的JavaScriptおれおれアドベントカレンダー2017 – 08日目
概要
=
で初期値を設定できます。
いままでこう↓してたのを、
1 2 3 4 5 6 7 | function findRestaurant(type) { if (type === undefined) { type = 'sushi' ; } // ... } |
こう↓書けます。
1 2 3 | function findRestaurant(type = 'sushi' ) { // ... } |
初期値が適用される場面
元のコードで条件として if (type === undefined)
を示しましたが、新しい書き方でも条件は同じです。
書かなかった場合だけでなく、明示的に undefined
を指定した場合も適用されます。
1 2 3 4 5 6 7 | function say(message = 'Yo!' ) { console.log(message); } say(); // => "Yo!" say(undefined); // => "Yo!" say( null ); // => null |
単純に元の if (type === undefined)
の置き換えって感じっすねー。
引数の設定
途中のものだけでも
Javaとかだと初期値って仮引数群の後ろからじゃないと与えられないと思うんですけど、JavaScriptだとそんなことなくて、なんと、途中にだけ付けることができます。
1 2 3 4 5 6 7 8 | function makeSushi(neta, shari = 'sumeshi' , wasabi) { console.log(neta, shari, wasabi); // ... } makeSushi(); // => undefined, "sumeshi", undefined makeSushi( 'tuna' ); // => "tuna", "sumeshi", undefined makeSushi( 'tuna' , 'katame' , true ); // => "tuna", "katame", true |
初期値のないもの wasabi
は当然 undefined
になります。
これも単純に元の if (type === undefined)
の置き換えって感じっすねー。
引数から引数を利用する
左から順に評価されていくので、左側の引数を使った初期値を設定することができます。
1 2 3 4 5 6 7 | function numbers(n = 1, m = n * n, l = n + m) { console.log(n, m, l); } numbers(); // 1, 1, 2 numbers(3); // 3, 9, 12 numbers(3, 5); // 3, 5, 8 |
うひゃあ。
改めて単純に元の if (type === undefined)
の置き換えって感じっすねー。
分割代入と組み合わせる
大変便利な分割代入については別稿参照。
便利だけどなかなか読みづらいので、ご利用は計画的に。
1 2 3 4 5 6 7 | function makeDog({ type = 'shiba' } = { type: 'mix' }) { console.log(type); } makeDog(); // "mix" makeDog({}); // "shiba" makeDog({ type: 'samoyed' }); // "samoyed" |
右辺 { type: 'mix' }
が引数自体の初期値で、左辺の type = 'shiba'
は分割代入時の初期値です。
正直ここちょっとよくわかってないです。
右辺は実行時に評価
関数を実行するとき、 undefined
が与えられた際、初期値(右辺)が評価されます。
この例↓だと毎回実行時の時刻になります。
1 2 3 | function sayTime(now = new Date()) { console.log(`It is ${now.getHours()}:${now.getMinutes()}:${now.getSeconds()} now.`); } |
やっぱり単純に元の if (type === undefined)
の置き換えって感じっすねー。
引数未指定時に例外
前項の仕様を使うと、必ず引数を書かせるようにもできます。
1 2 3 4 5 6 7 8 9 | function throwNewError(name) { throw new Error(name); } function sayTime(now = throwNewError( 'Now is required' )) { // ... } sayTime(); // Exception: Error: Now is required |
どこで見かけた話だったかな。例外発生個所が変な場所になっちゃうのであまり実用的ではない気がする。
ちなみに =
の右辺に throw
は書けないです。
参考
- ECMAScript 2015 Language Specification – ECMA-262 6th Edition
- 14.1 Function Definitions
- 14.1.18 Runtime Semantics: IteratorBindingInitialization … 引数の扱い
- 13.3.3 Destructuring Binding Patterns …
foo = xxx
とかの仕様 - 12.2.6 Object Initializer
=
- デフォルト引数 – JavaScript | MDN
- 分割代入 – JavaScript | MDN
初期値を適用する条件( undefined
を与えられたとき)の定義は見つけられませんでした。