矢印地獄、または古い問題の新しいサークル

起源



むかしむかし、JavaScript開発者は匿名関数を非常に好んでいました(実際、今では多くの人がそれらを使用することを好みます)。 「良いIDE以外で読むことができ、それから少し頭を打ちます。









次に例を示します。







例1:







$http.request('GET', '/api').then(function (data) { return data.arr.map(function (item) { item.props.filter(function (prop) { return !!prop; }).map(function (prop) { prop.a = prop.a * 2; return prop; }) }).filter(function (item) { return item.props.some(function (prop) { return prop.a > 10; }); }); }, function (error) { throw new TypeError(error); });
      
      





これは非常に簡単な例で、実際には100〜200行、または300行以上のコードを持つ「モンスター」に会いました。







かつて、各機能が個別に宣言され、それらへのリンクのみを使用する「機能設計テンプレート」への移行により、コードが美しく、整然としており、最も重要なのは読みやすくなりました。







たとえば、この例は次の形式を取ります。







例2:







 $http.request('GET', '/api').then(requestSuccessHandler, requestErrorHandler); function requestSuccessHandler(result) { return result.arr .map(transformResultArr) .filter(filterResultArr); function transformResultArr(item) { item.props .filter(checkProperty) .map(transformProperty) } function filterResultArr(item) { return item.props.some(filterProperty); } function checkProperty(prop) { return !!prop; } function transformProperty(prop) { prop.a = prop.a * 2; return prop; } function filterProperty(prop) { return prop.a > 10; } } function requestErrorHandler(error) { throw new TypeError(error); }
      
      





より多くのコードがありますが、このようなオプションを使用する方が簡単で、読みやすく、ディベースも簡単です。







しかし、すべての善は長続きしませんでした。







矢印関数



問題に入る前に、矢印関数とは何か、そしてそれらが到着してくれたものを見てみましょう。







矢印関数は、匿名関数の短い記録です。 原則として、これですべてですが、実際には非常に便利です。 たとえば、配列からidフィールドを持つすべての要素を選択する必要がある場合。 以前は、次のように記述されていました。







例3:







 arr.filter(function(item) { return !!item.id; });
      
      





または:







例4:







 arr.filter(filterID); function filterID(item) { return !!item.id; }
      
      





しかし、矢印関数を使用すると、このエントリは非常に短くなります。







例5:







 arr.filter(item => !!item.id);
      
      





すべてが素晴らしいようです。 そして、はい、ここで私は、矢印関数が読みやすさを損なうことなくコードをより簡潔にしたことに同意します、そして、すべての単純な場合においてそうです。 そして、匿名の機能が満載された新しいスチールガイドがあるとすでに考えていましたが、存在しませんでした。







問題はすぐには現れません。







周りの矢印



最近、ECMAScript 2015が最初から積極的に使用される新しいプロジェクトに切り替えました。いつものように、言語の新しい機能が最大限に使用されています。 これらの中で最も注目すべきは、矢印関数の広範な使用です。 また、100行以上、4レベル以上のネストの関数の滝がなければ、すべてがうまくいきます。







明確にするために、最初の例に戻りましょう。このプロジェクトでは次のようになります。







例5:







 $http.request('GET', '/api').then(data => { return data.arr.map(item => { item.props.filter(prop => !!prop) .map(prop => { prop.a = prop.a * 2; return prop; }) }).filter(item => item.props.some(prop => prop.a > 10)); }, error => { throw new TypeError(error) });
      
      





一般に、それは短くなりました(そして、ちなみに、コードが短い場合、私自身も大好きです)。 いくつかの場所では、より明確になりました。 ただし、これは最初の例と比較した場合のみです。 実際には、そのようなコードは巨大で読みにくいモンスターに成長し、すぐに記述されますが、その後議論され、何時間も取り組んでいます。







しかし、矢印の使用が悪いと言っているのではなく、矢印を適度に使用するだけです。







より良い方法は?



ECMAScript 2015で優れたプラクティスを作成するための道のりで、私たちは長い間つまずいて倒れますが、最初に、ベストと古いプラクティスと新しいプラクティスの組み合わせを始めましょう。







たとえば、例2と5を組み合わせます。







例6:







 $http.request('GET', '/api').then(requestSuccessHandler, requestErrorHandler); function requestSuccessHandler(result) { return result.arr .map(transformResultArr) .filter(filterResultArr); function transformResultArr(item) { item.props .filter(prop => !!prop) .map(transformProperty) } function filterResultArr(item) { return item.props.some(prop => prop.a > 10); } function transformProperty(prop) { prop.a = prop.a * 2; return prop; } } function requestErrorHandler(error) { throw new TypeError(error); }
      
      





単純な1行関数に矢印関数を使用すると、コードの可読性を損なうことなく膨大な数の小さな関数を作成することを回避できますが、関数が1つのアクションよりも複雑な場合は、多くの場合、個別に取り出して他の開発者は、このコードセクションで何が起こっているかを簡単に理解できます。








All Articles