質問:arguments.calleeが駄目な理由はなんですか?
「arguments.callee
は使うな!」のような記事を以前に読んだのですが(探しても見つかりませんでした)、どうしてarguments.callee
を使ってはいけないと言われているのでしょうか?
またarguments.callee
はstrictモードでも禁止されていますよね。どうしてarguments.callee
がいけないのか、いくつか問題のある例をご提示していただけると嬉しいです。
個人的には「再帰していることを明示」できる点でarguments.callee
は良いとも思っています。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答2件
0
ベストアンサー
MDNのarguments.calleeの解説の所に理由が書いてました。
Why was arguments.callee removed from ES5 strict mode?
※ 該当部分は日本語未翻訳ですので、英語版をお読みください。
一見、無名関数での再帰関数に使うのに有用と思えますが、MDNで紹介されている下記のコードの場合に、問題が発生します。
JavaScript
1var global = this; 2 3var sillyFunction = function (recursed) { 4 if (!recursed) { return arguments.callee(true); } 5 if (this !== global) { 6 alert("This is: " + this); 7 } else { 8 alert("This is the global"); 9 } 10} 11 12sillyFunction();
このコードは次のような動作になります。
sillyFunction();
と引数無しで呼びます。
呼び出されたsillyFunction関数は次の環境で実行されます。
引数はありませんので、recursed
はundefinde値です。
レシーバが無い(関数だけの)呼び出しですので、this
は変数global
と同じになります。
2. !recursed
が真偽評価が真になりますので、return arguments.callee(true);
と引数付きで呼び出します。
呼び出されたsillyFunction関数は次の環境で実行されます。
引数はtrue
ですので、recursed
はtrue
です。
レシーバがarguments
ですので、this
は**最初に呼び出された時のarguments
**です。
3. !recursed
が真偽評価が偽になりますので、飛ばされます。
4. this
はもはや変数global
とは異なりますので、if文の真の方が実行されます。
5. this
がアラートで表示されます。**最初に呼び出された時のarguments
**になっている事がわかります。
JavaScriptでは、a.f(...)
という関数呼び出しをした場合、bind等でthis
があらかじめ束縛されていなければ、呼び出された関数f
の中でのthis
はa
になります。**arguments.callee(true)
という呼び出しでも同様にthis
がarguments
になるというだけです。**ですが、この最初の呼び出しと再帰での呼び出しでthis
が変わるという動作は思わぬバグを引き起こすため、名前付きの関数式を使うことが推奨されるようになったというのが理由のようです。
また、ES6からは末尾呼び出し最適化が仕様として追加されました(ただし、ほとんどのブラウザがまだ未実装です)が、arguments.callee
ではこの末尾呼び出し最適化によって再帰関数でもスタックを消費しないという動作の恩恵を受けることもないようです。(末尾呼び出し最適化は実装がほとんど無いため、ちょっと未確認ですが)
投稿2017/01/16 20:54
編集2017/01/16 20:56総合スコア21733
0
原則として「関数は名前を付けるべき」と考えています。
その方が分かりやすいですし、デバッグもしやすいからです。
関数名を付ければ再帰呼び出し可能なので arguments.callee
の出番はないのだと思います。
それなら「arguments
自体が不要では?」と思われるかもしれませんが、arguments[i]
は可変引数を作るときに有用なので…。
ES6(ES2015) で Rest parameters が出来た現在では必要性が低くなっていますが、arguments.length
にはまだ価値があるのでまだ必要性はありそうです。
Re: redstone さん
投稿2017/01/16 15:46
総合スコア18156
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/01/16 17:07
2017/01/17 01:26
2017/01/17 16:57 編集
2017/01/17 16:04
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/01/16 21:18 編集
2017/01/17 01:47 編集
2017/01/17 09:19