web-dev-qa-db-ja.com

JavaScriptのarguments.calleeは何のためのものですか

この変数の完全なクロスブラウザドキュメントは見つかりませんでした。

とは arguments.callee ために?それはどのように機能しますか?

それはどの引数を持っていますか?

23
Jordi P.S.

arguments.calleeは、現在呼び出されている関数への参照です。まず最初に、それを使用しないでください。厳密なコンテキストにいる場合は、エラーが発生します。

ただし、個人的には-and 私はこれだけではありません -このプロパティを見逃します。理由を説明する前に、これをいつ使用するかについての疑似例を示します。

var looper = (function(someClosureVar)
{
    setTimeout((function(resetTimeout)
    {
        return function()
        {
            //do stuff, stop OR:
            resetTimeout();
        };
    }(arguments.callee)),1000);
}(document.getElementById('foobar')));

私がそうするので、あなたがクロージャーが好きだといいのですが、それがarguments.calleeが発生する可能性が非常に高い場所です。最後から2番目の行は、お金がどこにあるかです。

(arguments.callee)

クロージャスコープ内で初期タイムアウトを設定する無名関数への参照です(この場合、1つのDOM要素にアクセスできます)。匿名関数は返された後にGCされますが、この場合は、タイムアウトコールバックのスコープに追加しました(実際のコールバックを返す別の匿名関数への引数として渡しました)ので、どこかで参照されます。
今、あなたが厳格である場合、これは厳格モードでのコードのようになるため、心配する必要はありません。

var looper = (function tempName(someClosureVar)
{
    setTimeout((function(resetTimeout)
    {
        return function()
        {
            //do stuff, stop OR:
            resetTimeout();
        };
    }(tempName)),1000);
}(document.getElementById('foobar')));

関数に名前を付ければ、それだけです。なぜ私はそれを好きではないのですか? arguments.calleeは、一部のクロージャトリックが行われている匿名関数と同様に、フラグを立てます。これは単なる習慣だと思いますが、コードの構造化とデバッグをより簡単にするのに役立つと思います。
これをIEの病的な憎悪と組み合わせると、クライアント側のスクリプトを作成する人には自然なことになります。 IEバージョンは、関数名をグローバル名前空間にleakする傾向があるため、決して関数に関連付けられたメモリ(および作成したクロージャ)をGCできるようにします。これにより循環参照につながる可能性があり、さらに悪いことに、循環DOM参照によりメモリリークが発生する可能性があります。

実際: ここに別の実際の例がありますarguments.calleeが使用される場所:イベントの委任とイベントリスナーの切り離し
ここにいくつかの詳細があります JS strictモードとarguments.calleeを使用した再帰。

最後の質問は、IMOがarguments.calleeがどのように便利であるかを示す最も明確な例です:再帰的な置換関数:

function someF(foo)
{
    //'use strict'; <-- would throw errors here
    foo = foo.replace(/(a|b)+/gi, function (p1,p2)
    {
        if (p1.match(/(a|b){2,}/i))
        {
            return p1.replace(/(a|b)/gi,arguments.callee);//recursive
        }
        return (p2.match(/a/i) ? 'X':'Y');
    });
}

要求に応じて arguments.callee をMDNで使用し、strictモードでの使用を警告します(ECMA 5は、DCがarguments.calleeが廃止予定である理由を説明しています)
そして 厳密についての詳細

31

CaleeはECMAScript 3標準の一部であるため、クロスブラウザーでの使用に対して安全である必要があります。呼び出し先は現在実行中の関数を保持しており、それを呼び出すと現在の関数が呼び出されます。したがって、呼び出し先は、囲んでいる関数とまったく同じ引数を取ります(または、現在の関数isです)。いくつかの詳細情報はここにあります: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

呼び出し先を使用するのは悪いスタイルと見なされます。代わりに関数に名前を付けて、この名前を使用してください...

4
Mathias Schwarz

現在実行中の関数を指定しているので、arguments.calleeは現在の関数です。匿名関数で再帰的にする必要がある場合に役立ちます。ここにmozillaの例があります:

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

var result = create()(5); // returns 120 (5 * 4 * 3 * 2 * 1)
4
Danil Speransky

calleeは、argumentsオブジェクトのプロパティです。その関数の関数本体内で現在実行中の関数を参照するために使用できます。

MDNドキュメントはこちら

2
benqus

arguments.calleeは、「この特定の引数をだれが呼び出しているのか」と尋ねることにより、現在実行中の関数を知る方法です。 。 。 。 。

_ function factorial(a){
    if(a>0)
      return a*arguments.callee(a-1);
 }
_

ここでfactorial(5)を呼び出すと、0より大きい条件がチェックされ、trueの場合は、次に小さい数値に対して同じロジックが実行されます。 。 。呼び出される関数の名前がわからない場合があります。 。 。 .soこのプロパティを使用できます

これは良い参考文献です

MDNからのarguments.callee

UPDATE:arguments.callee()はES5で廃止されました

2
palerdot