現代的JavaScriptおれおれアドベントカレンダー2017 – 03日目
便利ちょう便利。
要約
return
するだけの場合、ブロックとreturn
を省略できる- 一行の場合は自動的に
return
される - 引数がひとつだけの場合、括弧を省略できる
this
の扱いに注意arguments
の代わりに...args
を使おう
使い方
例えばオブジェクトの配列↓を、
const data = [ { id: 101, name: 'Alice' }, { id: 102, name: 'Bob' }, { id: 103, name: 'Charlie' }, ];
IDだけの配列へ変換したい場合、やっぱり配列の map()
を使うじゃないすか。
const ids = data.map(function(row) { return row.id; }); console.log(ids); // => [101, 102, 103]
これ↑をアロー関数にすると、こう↓です。
const ids = data.map((row) => { return row.id; }); console.log(ids); // => [101, 102, 103]
function
を書かなくてもよくなりました。そんなに変わってないかもしれないけど、まずはここから。
省略して一行にする
いったんとりあえずそのまま一行にしてみます。
const ids = data.map((row) => { return row.id; }); console.log(ids); // => [101, 102, 103]
今までも function
式でやってましたよね、こういうの。
さて、今回のように中身が一行だけの場合、なんと、ブロック {
~ }
を省略できます。
すると、こう↓書けます。
const ids = data.map((row) => row.id); console.log(ids); // => [101, 102, 103]
おおっと、思ったより消えましたね。
return
を省略する
実は一行のアロー関数にした場合、その =>
の右側が自動的に戻り値になります。そう、ブロックだけでなく return
すら省略できるのです。
ちなみに戻り値が必要ない場合でも return
はされますが、その値は捨てられるだけなので、特に問題はないです。逆に返しちゃいけない場合はブロック作って return undefined
してください。
引数の括弧を省略する
加えて、引数の数がひとつだけの場合、括弧も外すことができます。
すると、こう↓書けます。
const ids = data.map(row => row.id); console.log(ids); // => [101, 102, 103]
最後に名前も短くしてしまいましょう。ほらこの場合は入る値が明白だから。
const ids = data.map(v => v.id); console.log(ids); // => [101, 102, 103]
だいぶ短くなりましたね。
function
を単純にアロー関数へ置き換えられない場合
function
式をアロー関数で置き換えましたが、単純に置き換えできない場合もあります。
return
が特殊な場合this
を使っている場合arguments
を使っている場合new
する場合
このうち return
についてはもうやりました。
this
が変わらない
例えば、これは駄目な例。(バック側のひとも知ってるかなと思ってるけどどう?)
el.addEventLister('click', (event) => { console.log(this === el); // false });
function
だった頃は this
は対象の要素を指すことが期待されました。ところがアロー関数はそうはなりません。
this
は、アロー関数を実行した際の this
になります。例えばコントローラーオブジェクトとか、グローバルオブジェクトとか。要は、かつて var that = this
とか _this
とかやってたのがいらなくなる感じです。便利っすねー。
さてじゃあ今回のこれどうするかというと、次項。
クリック他のイベントからは event.currentTarget
で
対象の要素を取ってこれます。
// たまにはjQuery $('.sugoi-button').on('click', (event) => { const el = event.currentTarget; console.log(el); });
これはESではなくDOMの仕様。
arguments
が取れない
関数実行時の引数リストを得る arguments
なんですが、アロー関数の場合は普通の関数とは扱いが違うので、 arguments
が用意されません。その外側の関数の引数になっちゃいます。
数がわからない場合、可変長引数 (rest parameters)で引数を全部取れます。
const f = (...args) => console.log(`${args.length}個の引数ゲットだぜ`); f(); // => 0 f(1); // => 1 f('ピカチュー', 'カイリュー', 'ヤドラン', 'ピジョン'); // => 4
可変長引数については後日別稿を。
new
できない
コンストラクタになりません。
const Foo = () => {}; new Foo(); // TypeError: Foo is not a constructor
まあ this
が固定されるという話も合わせれば、そりゃそうだよねーという感じはします。
その他
矢印 =>
前は改行できない
なんか知らんけどそういう仕様になってます。
() => console.log('!'); // Exception: SyntaxError: no line break is allowed before '=>'
後ならよろしい。
引数がいらないなら _
とかにしたい
二文字 ()
打つより一文字 _
の方が良くない? そうでもない?
アンダースコアは「受け取るけど捨てる引数」という意味です。(仕様じゃなくて風習。他言語の。)
ただ、関数に定義されている引数の数って fn.length
で取れるんだけど、それを見て処理を変えてる場合はこれだと駄目です。例えばChaiのやつとか。
参考
- ECMAScript 2015 Language Specification – ECMA-262 6th Edition
- 14.2 Arrow Function Definitions – Syntax …
=>
前の改行について - 14.2.16 Runtime Semantics: Evaluation …
this
の扱いについて - 9.2.5 FunctionCreate (kind, ParameterList, Body, Scope, Strict, prototype) … 関数オブジェクトを作成する処理。アロー関数の場合は非コンストラクタとしてマークされる
- 9.2.12 FunctionDeclarationInstantiation(func, argumentsList) … 注釈として、アロー関数は
arguments
ないよって
- 14.2 Arrow Function Definitions – Syntax …
- アロー関数 – JavaScript | MDN
- Event.currentTarget – Web API インターフェイス | MDN
- Rest parameters – JavaScript | MDN … 可変長引数、のようなもの。まだうまい日本語名付いてないみたい
- Javascript ES6, why I can not use
new
with arrow function? – Stack Overflow - DOM Standard – 2.2. Interface Event …
event.currentTarget