1. ホーム
  2. javascript

[解決済み] Javascriptのarguments.calleeは何のためにあるのでしょうか?

2022-02-07 07:03:55

質問内容

この変数に関するクロスブラウザの完全なドキュメントを見つけられませんでした。

とは何ですか? arguments.callee どのように機能するのですか?

どのような引数があるのですか?

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

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のバージョンは、以下のような傾向があります。 リーク そのため、関数(と作成したクロージャ)に関連するメモリがGCされることは決してありません。そのため、関数(と作成したクロージャ)に関連するメモリがGCされることはありません。これは、循環参照や、さらに悪いことに、循環DOM参照につながり、メモリリークにつながる可能性があります。

実は もうひとつ、実際の例を挙げましょう。 どこの arguments.callee は、イベントの委譲とイベントリスナーのデタッチに使用されます。
詳しくはこちら を使用したJSストリクトモードと再帰について説明します。 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');
    });
}

ご要望にお応えして 引数.callee MDN では、ストリクトモードでの使用について警告しています (ECMA 5、DC が arguments.callee を非推奨としている理由がわかります)。
そして ストリクトの詳細