JavaScriptでまだ関数を使用しているのはなぜですか?

私は、Habrahabrの読者に、Bill Sourourによる記事「Constant confusion:JavaScript function statementをまだ使用する理由」の無料翻訳を提供しています。



90年代に戻って、私がJavaScriptを習っていたとき、 function



演算子を使用して「Hello World」を記述しようとしました。 このようなもの:



 function helloWorld() { return 'Hello World!'; }
      
      





現在、タフな人は次のような「Hello World」関数を書いています。



 const helloWorld = () => 'Hello World!';
      
      





ES2015標準でJavaScriptに追加された矢印関数を使用します。 彼女はとても美しく見えます。 すべてが1行に収まります。 簡単に。 とても素晴らしい。



当然のことながら、矢印関数は新しい標準の最も一般機能の1つになりました。



初めて見たとき、私はフューチュラマのフライのように見えました



画像

バベルが無料であることを考慮しても



JavaScriptを20年間学習し、いくつかのプロジェクトでES2015を使い始めた後、今日のHello Worldをどのように書きますか? このように:



 function helloWord() { return 'Hello World!'; }
      
      





新しい方法を示した後は、上記の「古い学校」のコードを見ることすらほとんどありません。



このような小さな単純な関数の場合、最大3行か。 なぜそんなに多くの余分なキャラクターがあるのですか?



私はあなたが考えていることを知っています:



画像

誰もこれをする時間がありません!



矢印関数が好きではないと思い込まないでください。 しかし、コード内でトップレベル関数を宣言する必要がある場合は、昔ながらの関数演算子を使用します。



マーティン「ボブおじさん」からのこの引用から、なぜ私がこれをしているのかが明らかになることを願っています。



コードの読み取りに費やした時間と書き込みに費やした時間の比率は10対1です。新しいコードに取り組んでいる間、古いコードを常に読み取ります。



この比率が高すぎるという事実により、コードを書くのにより多くの労力がかかるという事実にもかかわらず、将来のコードの読み取りが簡単でリラックスできるようにしたいと考えています。



Robert Martin:純粋なコード:作成、分析、リファクタリング


function



演算子には、矢印関数よりも2つの明確な利点があります。



利点#1:意図の明確さ



1日に数千行のコードを見るとき、プログラマの意図をできるだけ迅速かつ簡単に理解することが役立ちます。



これを見てください:



 const maxNumberOfItemsInCart = ...;
      
      





すでにほぼ行全体を見てきましたが、省略記号の代わりに何があるか、つまり、関数または値を理解できません。 次のようになります。



 const maxNumberOfItemsInCart = 100;
      
      





...など:



 const maxNumberOfItemsInCart = (statusPoints) => statusPoints * 10;
      
      





関数演算子を使用する場合、あいまいさはありません。



以下をご覧ください。



 const maxNumberOfItemsInCart = 100;
      
      





...に対して:



 function maxNumberOfItemsInCart(statusPoints) { return statusPoints * 10; }
      
      





プログラマーの意図は、行の最初から明確です。



おそらく、構文が強調表示されたコードエディターを使用している可能性があります。 たぶんあなたは速く読んでいます。 むしろ、数行追加しても大きなメリットは得られないと思うでしょう。



分かりました。 短いレコードはまだかなり魅力的に見えます。



実際、これが私の唯一の理由であれば、読みやすさが犠牲になる可能性があることを自分に納得させることができるでしょう。



それでも、これが私の唯一の理由ではありません。



利点2:発表の順序==実行の順序



理想的には、実行したい順序でコードを宣言したいと思います。



しかし、矢印関数を使用する場合、これは私にとって障害になりますconst



を介して宣言された値は、コード実行が到達するまで利用できません



画像

私が話していることを理解していることを証明する必要がある(私は願っています)



以下に書かれていることで理解する必要があるのは、宣言する前にconstを使用できないことだけです。



このコードはエラーを引き起こします:



 sayHelloTo('Bill'); const sayHelloTo = (name) => `Hello ${name}`;
      
      





これは、JavaScriptエンジンがコードを読み取る時点で、sayHelloTo関数のバインディングを作成しますが、初期化はしないためです。



すべてのJavaScript広告は初期段階で固定されていますが、異なる時間に初期化されます。 つまり、JavaScriptは定数「sayHelloTo」の宣言をバインドし、それを読み取って上に移動し、メモリ内の場所をストレージに割り当てますが、実行時に到達するまで値を設定しません。



sayHelloToバインディングとその初期化の間の時間は、テンポラルデッドゾーン(TDZ)と呼ばれます。



Babelを使用してコードをES5に変換せずにブラウザーでES2015を直接使用すると、以下の例でもエラーがスローされます。



 if(thing) { console.log(thing); } const thing = 'awesome thing';
      
      





ここでconstvarに置き換えた場合、エラーは発生しません。 事実は、定数とは異なり、バインド中に変数が未定義の値で初期化されるということです。 しかし、私が脱線する何か...



関数演算子は、 constとは異なり、TDZ問題の影響を受けません。 このコードは有効です:



 sayHelloTo('Bill'); function sayHelloTo(name) { return `Hello ${name}`; }
      
      





これは、 関数演算子を使用すると、バインディングの直後-コードが実行される前に関数を初期化できるためです。



したがって、機能コードがどこにあるかは重要ではなくなり、実行の最初から利用可能になります。



constを使用すると、面倒なコードを記述できます。 まず、低レベルの関数を使用して作業を開始し、それから次第に高くする必要があります。 私の脳はこの方向では機能しません。 詳細を詳しく説明する前に、全体像を確認したいと思います。



ほとんどのコードは人々によって書かれています。 したがって、ほとんどの人の理解は、実行の順序に直接関係していることを考慮する価値があります。



実際、コードの冒頭でAPIのごく一部の簡単な要約を提供するのは素晴らしいことではないでしょうか? 関数演算子を使用すると、これを簡単に行うことができます。



商品のバスケットについては、この(部分的に構成された)モジュールをご覧ください...



 export { createCart, addItemToCart, removeItemFromCart, cartSubTotal, cartTotal, saveCart, clearCart, } function createCart(customerId) {...} function isValidCustomer(customerId) {...} function addItemToCart(item, cart) {...} function isValidCart(cart) {...} function isValidItem(item) {...} ...
      
      





矢印関数を使用すると、次のようになります。



 const _isValidCustomer = (customerId) => ... const _isValidCart = (cart) => ... const _isValidItem = (item) => ... const createCart = (customerId) => ... const addItemToCart = (item, cart) => ... ... export { createCart, addItemToCart, removeItemFromCart, cartSubTotal, cartTotal, saveCart, clearCart, }
      
      





ここで、これが膨大な数の小さな内部関数を持つ大きなモジュールであると想像してください。 その場合、何を好むでしょうか?



発表の前に何かを使用することは不自然であり、未知の結果につながる可能性があると主張する人々が必ずいるでしょう。 これを主張する人は一流の専門家であり、自分の分野を理解することができますが、これはあなたの意見であり、確認された事実ではありません。



コードはコミュニケーションの手段だと思います。 本当に良いコードは一流の物語を伝えることができます。 コンパイラ、トランスパイラー、およびミニマイザーがマシンのコードを最適化できるようにします。 しかし、私自身は、自分に書かれていることを理解したい単純な人のために、コードを最適化したいと思っています。



それでは、矢印関数についてはどうでしょうか?



はい 彼らはまだ美しいです。



通常、矢印関数を使用して、小さな関数を値として関数レベルアップに渡します。 promisemapfilterreduce使用します。 これは彼らが素晴らしい選択になる場所です。



以下に例を示します。



 const goodSingers = singers.filter((singer) => singer.name !== 'Justin Bieber'); function tonyMontana() { return getTheMoney().then((money) => power) .then((power) => women); }
      
      





これで私はおそらく終了します。 読んでくれてありがとう!



All Articles