現代的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
newwith arrow function? – Stack Overflow - DOM Standard – 2.2. Interface Event …
event.currentTarget