[解決済み] javascriptの関数を再帰的に呼び出す
質問
変数の中に再帰的な関数を作ることができます。
/* 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がアクセスされた場合、インライン化されていない関数への参照を提供できるようにする必要があるためです。
関連
-
[解決済み] JavaScriptで "use strict "は何をするのか、その根拠は?
-
[解決済み] JavaScriptで文字列が部分文字列を含むかどうかを確認する方法は?
-
[解決済み] あるJavaScriptファイルを他のJavaScriptファイルにインクルードするにはどうすればよいですか?
-
[解決済み] JavaScriptでタイムスタンプを取得する方法は?
-
[解決済み】JavaScriptの比較では、どちらの等号演算子(== vs ===)を使うべきですか?
-
[解決済み】JavaScriptの関数にデフォルトのパラメータ値を設定する
-
[解決済み】オブジェクトからプロパティを削除する(JavaScript)
-
[解決済み] CORS OriginヘッダーとCSRFトークンによるCSRF保護
-
[解決済み] JSHintの'+'前の改行不良の説明
-
[解決済み] jQueryを使用して、すべてのクリックイベントハンドラを削除するにはどうすればよいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] AngularJSのエラーです。Cross Origin リクエストはプロトコルスキーム http, data, chrome-extension, https に対してのみサポートされています。
-
[解決済み] javascriptで2つの数値を連結する方法は?
-
[解決済み] 無効になっている入力フィールドの値を送信する
-
[解決済み] サブドメインにまたがってlocalStorageを使用する
-
[解決済み] Chromeの拡張機能開発にWebStormを使用するにはどうすればよいですか?
-
[解決済み] JavaScript のオブジェクトの配列を比較し、最小値/最大値を取得する
-
[解決済み] $.ajax実行中にローディングイメージを表示する
-
[解決済み] なぜjavascriptのES6 Promisesはresolve後も実行を継続するのですか?
-
[解決済み] JavaScriptの文字列プリミティブとStringオブジェクトの違いは何ですか?
-
[解決済み] Chrome拡張機能:popup.htmlを強制終了させる