JavaScriptで他の関数への引数として大きな匿名関数を渡すのはなぜそんなに広く受け入れられているのですか?


27

私が持っている意見、他の関数に引数として数行のコードよりも多く含まれている無名関数を渡すと、私はそれが希望を感じる点まで、大幅に読みやすさと自己のドキュメントに影響を与えることを(私は必ずいくつかによって共有されることになるのです)名前付き関数を宣言するためにコードを使用する可能性が高い人にとってははるかに優れています。または、少なくともメイン関数を宣言する前に、その匿名関数を変数に割り当てます

ただし、多くのJavaScriptライブラリ(jQuery、d3.js / NVD3.js)では、いくつかの例を示しただけで、このように大きな関数を使用しています。

これがなぜJavaScriptでこれほど広く受け入れられているのですか?それは文化的なものですか、名前付き関数を宣言するよりも使用する方が好ましいと思われる利点がありますか?


1
おそらくクロージャーの使用と関係があります。また、実際の関数を外部に公開したくない場合もあるかもしれません(これが匿名である理由です)。
ロバートハーヴェイ

3
@RobertHarveyつまり、JavaScriptがpublicprivateを持たないという回避策ですか?
メイソンウィーラー

2
多くの場所で、大規模な匿名関数はブロックのように読み取られ、一般的に慣れるとかなり良い感じになります。スコーピングルールは、ブロックの感触もサポートします。

5
@MasonWheeler:それはあなたの視点次第です。スキームやECMAScriptのプログラマがそれを言うかもしれないpublicし、private適切なクロージャを持っていないための回避策です。
ヨルグWミットタグ

1
@JörgWMittagHooray for Racket、XKCD 927の
メイソンウィーラー

回答:


23

私が考えることができる3つの主な理由:

  1. 親スコープアクセス
  2. プライバシー
  3. より高いスコープで定義された名前の削減

親スコープアクセス:インライン関数定義により、インラインコードは親スコープで定義された変数にアクセスできます。これは多くのことに非常に役立ち、適切に行うとコードの量や複雑さを軽減できます。

このスコープ外で定義された関数にコードを配置してからコードを呼び出す場合、関数にアクセスしたい親状態を渡す必要があります。

プライバシー:インライン匿名定義内のコードはよりプライベートであり、他のコードから呼び出すことはできません。

上位のスコープで定義された名前の削減: これは、グローバルスコープで操作する場合に最も重要ですが、インライン匿名宣言により、現在のスコープで新しいシンボルを定義する必要がなくなります。Javascriptはネイティブで名前空間の使用を必要としないため、最低限必要なものよりも多くのグローバルシンボルを定義しないようにするのが賢明です。


社説:匿名でインラインで宣言することは、親スコープアクセスが使用されていない場合でも、関数を定義して呼び出すよりも「良い」と見なされるJavascriptの文化的なものになったようです。これは、最初はJavascriptのグローバルな名前空間の汚染の問題によるものであり、おそらくプライバシーの問題によるものと思われます。しかし、今やそれはやや文化的なものに変わっており、多くの公共のコード体系(あなたが言及したようなもの)で表現されていることがわかります。

C ++のような言語では、多くの場合、多くのページ/画面にまたがる1つの巨大な機能を持つことは理想的ではないと考えられます。もちろん、C ++にはネームスペースが組み込まれており、親スコープへのアクセスを提供せず、プライバシー機能を備えているため、Javascriptはコード式を使用してプライバシーと親スコープへのアクセスを達成する必要がありますが、完全に読みやすさ/保守性を高めることができます。そのため、JSは別の方向に動機付けられているように見え、特定の場合にその方向に動機付けられたものが必要でない場合でも、言語内の文化的なものになります。


C ++開発者が最近多くの私の仕事のためにJSに移行したため、この答えは非常に理にかなっています。特に「親スコープアクセス」ポイント-コードを大幅に簡素化する力があります。ワンピック-C ++はC ++ 11ラムダで親スコープへのアクセスを提供します:)間違いなく+1です。
コリアンダーサンショウウオ司令官

8

JavaScriptでは、ほとんどの言語よりも多くの目的で匿名関数が使用されます。

まず、これらはネームスペースとブロックスコープに使用されます。最近までJavaScriptにはモジュールや他の種類の名前空間メカニズムがなく、匿名パターンを使用してモジュールパターンを介してその機能を提供していました。これらの関数に名前を付けることにはまったく利点がありません。JavaScriptには最近までブロックスコーピングがなかったため、小規模では、ブロックスコーピングを模倣するために同様のパターンが使用されました。最も顕著なのはループの本体です。この場合、名前付き関数を使用すると、積極的に難読化されます。

第二に、JavaScript固有ではない匿名関数は、制御構造を模倣する高次関数とともに使用されることがよくあります。たとえば、jQueryのeachメソッド。数行以上の長さがある場合は、すべてのループ本体またはif-branchを関数に抽象化することを疑います。この場合、同じロジックが適用されます。

最後の理由は、JavaScriptでイベントベースのプログラミングが一般的であるため、意図しない継続渡しスタイルコードが発生する傾向があることです。AJAX呼び出しを行い、コールバックを登録します。実行すると、別のAJAX呼び出しを行い、コールバックを登録します。呼び出しが非同期ではなく同期の場合、これは単一のレキシカルスコープ内のコードの直線シーケンスになります。 。繰り返しになりますが、直線コードの数行ごとを抽象化して関数にするとは思いません。

文化的な要因もあり、特に上記の理由により、匿名関数は他の多くの言語よりもJavaScriptではるかに一般的であり、他の多くの言語よりも快適/ゆるやかに使用されています。


私自身のC ++コーディングのおそらくナイーブな構造は、std :: functionおよびlambdasを介してJavaScriptからイベントベースのコーディングとコールバックの原則をとることがあります。私の場合、部分的には、C ++でUIコードを実行しており、ブロッキング操作を実行したくないためです。JavaScriptのプラクティスが、言語がそれらを適切にサポートしている限り、誰にとっても単に有用であるかどうか、私は興味があります。
Katana314
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.