質問: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と同じになります。!recursedが真偽評価が真になりますので、return arguments.callee(true);と引数付きで呼び出します。
呼び出されたsillyFunction関数は次の環境で実行されます。
引数はtrueですので、recursedはtrueです。
レシーバがargumentsですので、thisは**最初に呼び出された時のarguments**です。!recursedが真偽評価が偽になりますので、飛ばされます。thisはもはや変数globalとは異なりますので、if文の真の方が実行されます。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総合スコア21823
0
原則として「関数は名前を付けるべき」と考えています。
その方が分かりやすいですし、デバッグもしやすいからです。
関数名を付ければ再帰呼び出し可能なので arguments.callee の出番はないのだと思います。
それなら「arguments 自体が不要では?」と思われるかもしれませんが、arguments[i] は可変引数を作るときに有用なので…。
ES6(ES2015) で Rest parameters が出来た現在では必要性が低くなっていますが、arguments.length にはまだ価値があるのでまだ必要性はありそうです。
Re: redstone さん
投稿2017/01/16 15:46
総合スコア18196
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/01/16 21:18 編集
2017/01/17 01:47 編集
2017/01/17 09:19