JavaScriptで関数っぽいんだけど、見たことないものをここ数年見かけます。
『どうせシンタックスシュガーでしょ?』と、まぁなんとなく分かっていたのでほっといたのですが、それはいかんだろうということできちんと調べました。
まず答えを言うと、シンタックスシュガーではありません。ES2015(ES6)から導入された新しい記法でした。
シンタックスシュガー(syntax sugar, 糖衣構文)
プログラムで、読みやすさ、書きやすさのために導入された書き方。
ドキュメントや書籍などの書式で多く出てくるものではなく、たまに出てくるので『通好み』『デキる人の書き方』に見られることが多い。
ECMAScript(エクマスクリプト)
JavaScriptの仕様のこと。Ecma International(エクマ・インターナショナル)がJavaScriptの書き方を決めている(仕様の策定・勧告)。
実質的な策定作業はTC39が行い、それに基づいてEcma Internationalが勧告する。勧告されると『ES20**(年代)』という名称がつけられる。
Ecma Internationalは、もともとヨーロッパの電子通信に関する標準化団体なので、JavaScriptだけを扱っているわけではない。
ES2015(ES6)
2015年に策定された第6版のこと。JavaScriptの従来の書き方から大幅に改善されたので、インターネット上の情報も多い。
ES2015から1年ごとに仕様を勧告することになったので、公式の名称では版数を使うのをやめた。(ES6は昔の言い方の名残り。正式なドキュメントには書いてある。)
ES6という呼び方は、変化の過渡期なので許されているだけ。
ES2016
2016年に勧告された仕様。ES7という表現が見られるが、ES2016のほうが分かりやすいのでES6ほど一般的じゃない。
ES5
2015年に大幅な変更が行われる前のJavaScriptの仕様。第5版。2009年に勧告。現在、どんなに古いバージョンのブラウザでも動かすことができる基準になっている。
JavaScriptのトランスパイルが簡単にできるようになったので、すべてのブラウザに対応できるJavaScriptの呼び方として使われる。
(トランスパイルは別のバージョンのJavaScriptのプログラムに変換すること。)
ESNext
次世代のJavaScriptの仕様のこと。まだ勧告されていなくてTC39で策定中の仕様のことを指す。
すべてのブラウザが対応していないES2015以降を指して使っていることも多い。
トランスパイルが簡単になったので、Reactなどのフレームワークや、Node.jsのプラグイン開発など、ESNextでプログラミングすることが当たり前になっている。
次世代の仕様なので、短くかんたんに書けることも多く、SPA(Single Page Application)などの大規模・複雑な開発で使われる。
もちろん、Nextの範囲はES20**がリリースされるごとに変わる。その状況は下記リンクにある。
TC39(Technical Committee 39, 専門委員会39)
ECMAScriptの仕様の策定を行う専門委員会。Ecma InternationalはいろいろなTCを持っているので番号が振られている(ECMAScriptの仕様は39)。
作業中の内容や仕様などはGitHubで公開されていて確認できる。
作業は5ステージに分けて行い、すべてのステージが終了するとEcma Internationalが勧告する。
Stage 0 | Strawman たたき台・試案 | どんな仕様を導入するか? 策定作業に 入るか? を決める。 |
Stage 1 | Proposal 提案 | 仕様の策定作業の枠組みを作ったり問 題点の洗い出しを行う。 |
Stage 2 | Draft 下書き・草案 | JavaScriptでじっさいに書く。 プログラミングの書き方を決める。 ドキュメントには『正確に』とあるの で、あいまいなことは残さない。 |
Stage 3 | Candidate 候補 | 一般の開発者にドラフトを公開してフ ィードバックする。 (お試し期間) |
Stage 4 | Finished 完了 | ECMAScriptの標準に追加できる準備 ができている状態。 いつでも勧告できることを表す。 |
各ブラウザは、勧告されるのを待っているわけではなく、独自に先行して導入することもある。その経過は誰でも確認できる。
まずは、よく見かけるJavaScriptの関数の書き方から。
function plus(a, b) {
return a + b;
}
console.log(plus(1, 4));
これはかんたんですね? ほかのプログラム言語でも見る書き方です。コンソールログにplus()の結果『5』が表示されます。
var plus = function(a, b) {
return a + b;
}
console.lgo(plus(a, b));
もう一つ、無名関数と呼ばれるものです。JavaScriptやPHPなどWeb系のプログラム言語ではよく見る使い方。
関数を変数に格納できるオブジェクトとして扱い、その変数から関数をコールするやり方です。オブジェクトなので、そのまま関数の引数に指定することもできます。
無名関数では、よく『ラムダ式』『関数型プログラム』の言葉が出てきますが、調べるとまずいです。迷走します。ここではスキップしてください。
これらの言葉が分からなくても『百聞は一見に如かず』で、内容を見れば分かります。
ラムダ式、関数型プログラムは説明によって内容がまちまちです。でも間違いじゃないところが困りもの。
もともとの意味をたどるとまったく意味不明のところにたどり着くのでもっと困ります。
また、『関数リテラル』という言葉も出てきますが、深く考えすぎず『関数リテラル = 無名関数』と覚えたほうがいいです。
リテラル(literal)
ありのまま。文字どおりという意味から、プログラムに直接書くという意味。
let num = 1;
let str = "string";
let arr = ['arr1', 'arr2', 'arr3'];
let obj = {ojb1:"xxx", obj2:"yyy"};
これらの右辺はすべてリテラル。配列の場合は配列リテラル、オブジェクトの場合はオブジェクトリテラルという。
リテラルと定数は異なるということに注意が必要。
定数 | 値が変更できない変数のこと。 式の左辺。 |
リテラル | 定数に入れる固定値。 式の右辺。 |
無名関数(匿名関数)のことを関数リテラルという。無名関数は関数の引数に直接書くことがあるので『直接書いた関数 = リテラルな関数』と呼ばれる。
しかし、関数リテラルの意味をきちんと考えると迷走することがあるので、たんに『無名関数 = 関数リテラル』と覚えたほうが良い。
(じゃあ普通の名前付き関数は、直接書かれたもの(リテラル)じゃないのか? と思ってしまう。)
アロー関数は無名関数の新しい記法
やっと本題です。ES2015では無名関数に新しい書き方が加わりました。
let plus = (a,b) => { return a + b };
let plus = (a,b) => a + b;
まず上のコードの説明から。矢印(アロー, arrow)の左の()が関数の引数で、矢印の右の{}内が関数の処理の内容です。
そして、アロー関数がシンタックスシュガーでない理由がここから。この関数には省略形が存在します。シンタックスシュガーがあるということですね?
それが下のコードの書き方です。
- 処理が1文なら、{}はなくてもいい。
- 処理が1文でreturn構文だけなら、returnはなくてもいい。
- 引数が1つなら、()はなくてもいい。
1文がreturnじゃない場合どうなるかというと、returnで返されちゃいます。でもその処理自体、戻り値を期待していないので無視すればいいだけ。
(返すものがない場合、undefinedを返す。)
引数が1つの場合は()が省略できます。例がなかったので、こんな感じです。
let plus = a => a * 2;
aを2倍にした値がplusに入ります。
引数がない場合、()は省略できません。
let plus = () => 1 + 5;
plusに『6』が入ります。
オブジェクトを戻り値にする場合、注意が必要です。
let plus = () => {test1:"xxxxx", test2:"yyyyy"};
これはエラーになります(Uncaught SyntaxError: Unexpected token)。
{}がオブジェクトのものではなく関数の{}だと勘違いするから。この場合は()でくくります。
let plus = () => ({test1:"xxxxx", test2:"yyyyy"});
いろいろありますが、『こんなに略したら分からなくなるでしょ!』っていうくらいすっきりしています。
慣れるまでしばらく???が続きそうです。
このほか、thisの扱いが変わるなどあるのですが、それは別の機会に。とりあえずここまで。