「太い」矢印関数(=>)は、矢印関数とも呼ばれ、ECMAScript 2015(以前のES6)の完全に新しい機能です。 噂を信じるなら、ECMAScript 2015では
CoffeeScriptの影響下で->構文の代わりに=>構文が使用されました。 また、このコンテキスト転送の類似性が重要な役割を果たしました。
矢印関数には2つの主なタスクがあります。より簡潔な構文を提供するため。 レキシカルなthisに親スコープを提供します。 それぞれを詳しく見てみましょう!
新しい関数の構文
JavaScriptの関数の古典的な構文は、1つの変数を含む関数であっても、多くの関数を含むページであっても、堅固です。 関数を宣言するたびに、function(){}を記述する必要があります。 関数のより簡潔な構文の必要性は、
CoffeeScriptがかつて非常に人気を博した理由の1つでした。 この必要性は、小さなコールバック関数の場合に特に顕著です。 Promiseチェーンを見てみましょう。
function getVerifiedToken(selector) { return getUsers(selector) .then(function (users) { return users[0]; }) .then(verifyUser) .then(function (user, verifiedToken) { return verifiedToken; }) .catch(function (err) { log(err.stack); }); }
上部には、JavaScriptの古典的な関数構文を使用して記述された消化可能なコードが多少見られます。 そして、これは、矢印構文を使用して書き直されたまったく同じコードです。
function getVerifiedToken(selector) { return getUsers(selector) .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); }
ここでは、いくつかの重要な点に注意する必要があります。
- コールバック関数は1行で記述されているため、関数と{}を失いました。
- ()を削除しました。 現在は、引数が1つしかない場合は引数リストをラップしません(残りの引数は例外として渡されます。たとえば、(... args)=> ...)。
- returnキーワードを取り除きました。 {}を削除することにより、1行の矢印関数で暗黙的なリターンを実行できます(他の言語では、このような関数はラムダ関数と呼ばれます)。
もう一度、最後の点に注意してください。 暗黙的な戻りは、単一行の矢印関数でのみ発生します。 矢印関数が{}で定義されている場合、それが別個の演算子であっても、暗黙的な戻りは発生しません。
const getVerifiedToken = selector => { return getUsers() .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack)); }
ここから楽しみが始まります。 この関数には演算子が1つしかないため、{}を削除できます。コードは
CoffeeScript構文に非常に似ています。
const getVerifiedToken = selector => getUsers() .then(users => users[0]) .then(verifyUser) .then((user, verifiedToken) => verifiedToken) .catch(err => log(err.stack));
それでも、上記のコードはES2015構文を使用して記述されています。 (
完全に
コンパイルされたことにも驚きました。)矢印関数について1人のオペレーターと話すとき、これはオペレーターが使いやすいように複数の行を占有できないことを意味しません。
ただし、重要なマイナス点が1つあります。矢印関数から{}を削除すると、空のオブジェクトをどのように返すことができますか? たとえば、同じ{}?
const emptyObject = () => {}; emptyObject();
そして、ここに全体のコードがあります:
function () { return 1; } () => { return 1; } () => 1 function (a) { return a * 2; } (a) => { return a * 2; } (a) => a * 2 a => a * 2 function (a, b) { return a * b; } (a, b) => { return a * b; } (a, b) => a * b function () { return arguments[0]; } (...args) => args[0] () => {}
レキシカル本
彼らがどのようにこれをJavaScriptにドラッグしようとしたかという話は、すでにほこりっぽいものでした。 JavaScriptの各関数は、このための独自のコンテキストを設定します。 このコンテキストは、一方では非常に簡単に回避でき、他方では非常に迷惑です。 以下の例では、jQueryにアクセスしてデータを毎秒更新するウォッチのコードが表示されます。
$('.current-time').each(function () { setInterval(function () { $(this).text(Date.now()); }, 1000); });
setIntervalコールバックでそれぞれを介して指定された要素のこのDOMを参照しようとすると、残念ながら、コールバックに属するまったく異なるthisを取得します。 thatまたはself変数を設定することで、このポイントを回避できます:
$('.current-time').each(function () { var self = this; setInterval(function () { $(self).text(Date.now()); }, 1000); });
太い矢印関数はこの問題を解決するのに役立ちます。
$('.current-time').each(function () { setInterval(() => $(this).text(Date.now()), 1000); });
引数についてはどうですか?
矢印関数の欠点の1つは、通常の関数のように独自の引数変数がないことです。
function log(msg) { const print = () => console.log(arguments[0]); print(`LOG: ${msg}`); } log('hello');
繰り返しますが、矢印関数にはこれも引数もありません。 ただし、これを考慮すると、残りのパラメーター(スプレッド演算子とも呼ばれます)を使用して、矢印関数に引数を渡すことができます。
function log(msg) { const print = (...args) => console.log(args[0]); print(`LOG: ${msg}`); } log('hello');
ジェネレーターはどうですか?
太い矢印関数はジェネレーターとして使用できません。 例外や回避策はありません。 ポイント。
おわりに
「太い」矢印関数は、JavaScriptが大好きな理由の1つです。 関数の代わりに=>を使い始めるのは非常に魅力的です。 オプション=>のみが使用されているライブラリ全体を見ました。 しかし、これは合理的だとは思いません。 結局、=>には多くの機能と隠された機能があります。 新しい機能が必要な場合にのみ矢印関数を使用することをお勧めします。
- すぐに戻る単一の演算子を持つ関数。
- 親スコープでこれで動作する関数。
ES6今日
ES6を今日利用することは可能ですか? トランスパイラーの使用は、ここ数年で標準になりました。 単純な開発者も大企業も、それらを使用することに恥ずかしくない。
BabelはES6からES5へのトランスポーターであり、ES6のすべての革新をサポートします。
Browserifyを使用する場合は
、 わずか数分で Babelを追加できます。 もちろん、Node.jsを使用したほとんどすべてのビルドがサポートされています。 例:Gulp、Grunt、その他多数。
ブラウザはどうですか?
ほとんどのブラウザは
徐々に新しい機能を追加していますが 、まだ誰も完全にサポートしていません。 何、今待って? 状況によります。 1、2年後には一般的になる言語機能を使い始めるのは理にかなっています。 これにより、新しいステージに快適に移動できます。 ただし、ソースコードを完全に制御する必要がある場合は、ES5を待って使用することをお勧めします。
翻訳者:
greebn9k (セルゲイ・グリブニャック)、
silmarilion (アンドレイ・ハカレフ)