現代的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のやつとか。

参考