1. ホーム
  2. javascript

[解決済み] javascriptの関数を再帰的に呼び出す

2023-02-25 07:47:38

質問

変数の中に再帰的な関数を作ることができます。

/* Count down to 0 recursively.
 */
var functionHolder = function (counter) {
    output(counter);
    if (counter > 0) {
        functionHolder(counter-1);
    }
}

これを使って functionHolder(3); とすると、出力は 3 2 1 0 . 次のようにしたとします。

var copyFunction = functionHolder;

copyFunction(3); と入力すると 3 2 1 0 のようになります。もし私が functionHolder を以下のように変更します。

functionHolder = function(whatever) {
    output("Stop counting!");

次に functionHolder(3); とすると Stop counting! となります。

copyFunction(3); では 3 Stop counting! を参照するように functionHolder を参照しているため、関数(それ自体が指している)ではなく、を参照しています。これはある状況では望ましいことかもしれませんが、関数を保持する変数ではなく、それ自体を呼び出すように書く方法はありますか?

つまり だけ という行を functionHolder(counter-1); というように、これらのステップを踏んでも 3 2 1 0 を呼び出すと copyFunction(3); ? 試しに this(counter-1); を試してみましたが、これではエラーが発生します。 this is not a function .

どのように解決するのですか?

名前付き関数式を使用する。

関数式に名前をつけることができます。 プライベート であり、関数ifselfの内部からしか見えない名前をつけることができます。

var factorial = function myself (n) {
    if (n <= 1) {
        return 1;
    }
    return n * myself(n-1);
}
typeof myself === 'undefined'

ここで myself 関数の内部でのみ表示されます。 の中だけで見ることができます。

このプライベート名を使って、関数を再帰的に呼び出すことができます。

参照 13. Function Definition の ECMAScript 5 仕様を参照してください。

FunctionExpression の Identifier は、FunctionExpression の FunctionBody 内部から参照することができ、関数が自分自身を再帰的に呼び出すことを可能にします。しかし、FunctionDeclaration とは異なり、FunctionExpression の Identifier は FunctionExpression を囲むスコープから参照することはできず、影響も与えません。

バージョン 8 までの Internet Explorer では、名前が実際に囲む変数環境に表示され、実際の関数の複製を参照するため、正しい動作にならないことに注意してください ( patrick dw のコメント参照)。

arguments.calleeを使っています。

別の方法として arguments.callee を使って、現在の関数を参照することもできます。

var factorial = function (n) {
    if (n <= 1) {
        return 1;
    }
    return n * arguments.callee(n-1);
}

ECMAScript第5版では、arguments.callee()を ストリクトモード しかし

(以下 MDN ): 通常のコードでは、arguments.calleeは内包する関数を指します。この使用例は弱く、単に囲む関数を指定するだけです。さらに、arguments.calleeは関数のインライン化などの最適化の妨げになります。arguments.calleeがアクセスされた場合、インライン化されていない関数への参照を提供できるようにする必要があるためです。