プロが教える店舗&オフィスのセキュリティ対策術

無名関数のメリットがよくわかりません。
関数式にするのと、通常の関数を使いわけるメリットがよくわかりません。
たしかに関数式のほうがわかりやすそうですが、ぼんやりとしている感じです。
メリットを教えてください。

A 回答 (2件)

余談ですが、実はJavaScriptの作者(ブレンダン・アイク)はLisp言語のうちの一つ、Schemeが大好きで、JavaScriptは構文の見かけはC言語に似てますが、内部的にはSchemeをモデルに作られた、と言う話があります。


JavaScriptは一時、「Cの皮を被ったLisp」等とも言われていました。

JavaScript: 世界で最も誤解されたプログラミング言語:
https://web.archive.org/web/20130120204931/http: …

「皮を被ってる」んですよ、皮を。上野クリニック案件です(謎)。

さて、そういうトコで、Lisp/Scheme視点でJavaScriptの「無名関数」を語ってみましょう。
とは言っても、Lisp/Scheme由来の「無名関数」、基本的な使いどころはたった2つです。

1. 高階関数(JavaScriptの場合、実際は高階メソッドって言った方が良さそうですが)の引数として使う。

「高階関数」とは「関数を引数に取る関数」の事です。
これ、ここで例を挙げても良いんですが、別のページを参照してもらった方が、例が豊富なんで良さそうです。

JavaScript 高階関数を説明するよ:
https://qiita.com/may88seiji/items/8f7e42353b690 …

ここでのArrayオブジェクトのforEach, map, filter, sort, reduceといったメソッドの紹介例は全て引数に無名関数を渡しています。
実際はここで書かれてる無名関数を取り出して、別に関数にして定義して呼び出しても良いのですよ。ただ、世の中には、「一回使いたいだけで、別に使い回しが目的じゃない」と言う関数と言うかそういう状況がありまして、そのためにソースコード上に余計な関数を増やしたくねぇなぁ、とか言う場合が多々あるのです。
そう、「一回だけ高階関数の引数に使いたい」場合、無名関数の出番なのです。逆に、高階関数の引数だけじゃなく、別のトコでも使いそうだな、って予定/予感があったら、キチンと関数定義した方がよい。
普通の関数と無名関数は、恋人と行きずりの女の違いのようなモンです。恋人は何回もしますし、当然相手の名前を覚えてない、と言ったら失礼どころか殺される可能性がありますが、行きずりの女は一回ヤるだけ、名前なんて覚えててもしょーがないのです。そういう事です(謎

2. 関数を返す関数を書きたい場合、返り値として使う。

これが多分、どっちかと言うと馴染みがないでしょうね。
一番単純な例としては、アキュムレータと言うモノがあります。

function acc(n) {
 return function (i) {
     return n += i } }

関数accの内側を見れば分かるでしょうが、無名関数を返す構造になっていますね。
これは例えば、こういう風に使います。

js> var a = acc(5) // 変数 a に引数5を与えた acc を代入する
js> a(3)    // acc は返り値が無名関数だったので、変数 a は関数として機能し、引数を取れる
8       // 変数 a は内部に最初に与えられたn = 5を持ってるので5 + 3で答えが8になる。
js> a(3)
11      // 内部に n を含む環境が無名関数によって保持されているので、nは先程の答えの8であり、8と新たな引数3を足して答えは11

このように、無名関数と変数の再代入を上手く使えば、ある状況に於いてのある「状態」と言うのを保持出来るんです。

これを利用した例としては、良く宿題にでるお馴染みのフィボナッチ関数があります。
フィボナッチ関数は、再帰の例として良く出てきて「非効率性」と説いたりされるブツですね。
JavaScriptで書けばこんなカンジですか。

function fib(n) {
 if (n == 0) return 0;
 else if (n == 1) return 1;
 else return fib(n-2) + fib(n-1);
}

「while使えばもっと効率的に書けるよ!」とか言う声もあるでしょうが、本題はそこじゃない。
上のアキュムレータの例を応用すれば無名関数を使って次のように実装可能です。

function fib() {
 var a = 0, b = 1;
 return function() {
 var c = a;
 a = b, b = c + b;
 return c;
 };
}

これは先程の通り、変数に代入して使います。

js> var f = fib() // 変数 f に fib を代入
js> f()     // 変数 f は 実行する度にフィボナッチ数列上の数値を順繰りに吐き出していく
0
js> f()
1
js> f()
1
js> f()
2
js> f()
3
js> f()
5

つまり、知ってるかどうか知りませんが、Pythonで言うトコの「ジェネレータ」モドキがプログラミング出来るわけです。
これが意味するのが何かと言うと、先程の「フツーにプログラミングした」フィボナッチ数列にせよ、もっと効率が良いwhileを使ったバージョンにせよ、引数にnを与えて、それが条件が達するまで「計算」し続けないとなりません。「全ての計算結果が明らかにならないと」当然数値として返せないわけです。
一方、こっちの「無名関数を返す」ヴァージョンは内部に数値状態を保持してるわけですが、「呼び出すまで」計算が行われません。要するに無名関数がある意味「計算を止めてる」わけで、必要に応じて計算結果を返す、と言う事をしてるわけですね。

この2つが無名関数の大まかな使いどころです。
    • good
    • 2

下記サイトの「無名関数とは|「分かりそう」で「分からない」でも」をご覧ください。



https://wa3.i-3-i.info/word15754.html
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!