argument.callee.caller プロパティが JavaScript で非推奨になったのはなぜですか?

StackOverflow https://stackoverflow.com/questions/103598

  •  01-07-2019
  •  | 
  •  

質問

なぜそうなったのか arguments.callee.caller プロパティは JavaScript で非推奨になりましたか?

これは JavaScript で追加されてから非推奨になりましたが、ECMAScript では完全に省略されました。一部のブラウザ (Mozilla、IE) は常にこれをサポートしており、サポートを削除する予定はありません。他のブラウザ (Safari、Opera) ではこのサポートが採用されていますが、古いブラウザでのサポートは信頼できません。

この貴重な機能を保留にする正当な理由はあるのでしょうか?

(あるいは、呼び出し関数のハンドルを取得するより良い方法はありますか?)

役に立ちましたか?

解決

JavaScript の初期バージョンでは名前付き関数式が許可されていなかったため、再帰関数式を作成できませんでした。

 // This snippet will work:
 function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 }
 [1,2,3,4,5].map(factorial);


 // But this snippet will not:
 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : /* what goes here? */ (n-1)*n;
 });

これを回避するには、 arguments.callee が追加されたので、次のことができるようになりました。

 [1,2,3,4,5].map(function(n) {
     return (!(n>1))? 1 : arguments.callee(n-1)*n;
 });

ただし、これは実際には非常に悪い解決策でした。これは (他の引数、呼び出し先、呼び出し元の問題と併せて) 一般的なケースではインライン化と末尾再帰を不可能にしてしまいます (トレースなどを使用して特定のケースでは実現できますが、最良のコードであっても)他の方法では必要のないチェックが行われるため、最適ではありません)。もう 1 つの大きな問題は、再帰呼び出しが異なる結果を取得することです。 this 値、たとえば:

var global = this;
var sillyFunction = function (recursed) {
    if (!recursed)
        return arguments.callee(true);
    if (this !== global)
        alert("This is: " + this);
    else
        alert("This is the global");
}
sillyFunction();

いずれにせよ、EcmaScript 3 では、次のような名前付き関数式を許可することでこれらの問題を解決しました。

 [1,2,3,4,5].map(function factorial(n) {
     return (!(n>1))? 1 : factorial(n-1)*n;
 });

これには次のような多くの利点があります。

  • この関数は、他の関数と同様にコード内から呼び出すことができます。

  • 名前空間を汚染しません。

  • の値 this 変わりません。

  • パフォーマンスが向上します ( 引数オブジェクト 高いです)。

おっと、

他のすべてに加えて、質問が次のものであることに今気づきました arguments.callee.caller, 、またはより具体的には Function.caller.

いつでも、スタック上の関数の最も深い呼び出し元を見つけることができます。上で述べたように、呼び出しスタックを確認すると、次の 1 つの大きな効果があります。これにより、多くの最適化が不可能になるか、はるかに困難になります。

例えば。機能が保証できない場合 f 未知の関数を呼び出さないため、インライン化できません f. 。基本的に、これは、自明にインライン可能だった呼び出しサイトが多数のガードを蓄積することを意味します。

 function f(a, b, c, d, e) { return a ? b * c : d * e; }

js インタープリターが、呼び出しが行われた時点で提供されたすべての引数が数値であることを保証できない場合は、インライン化されたコードの前にすべての引数のチェックを挿入するか、関数をインライン化することができません。

この特定のケースでは、スマート インタプリタはチェックをより最適になるように再配置し、使用されない値をチェックしないようにする必要があります。ただし、多くの場合、それは不可能であるため、インライン化は不可能になります。

他のヒント

arguments.callええ.callえーっとない 非推奨ですが、 Function.callえーっと 財産。(arguments.callええ 現在の関数への参照を提供するだけです)

  • Function.callえーっと, は、ECMA3 によれば非標準ですが、世界中で実装されています。 現在のすべての主要なブラウザ.
  • arguments.callえーっと を支持して非推奨になりました Function.callえーっと, 、現在の主要なブラウザーには実装されていません (例:Firefox3)。

したがって、この状況は理想的とは言えませんが、すべての主要なブラウザで Javascript の呼び出し関数にアクセスしたい場合は、 Function.callえーっと プロパティ。名前付き関数参照で直接アクセスするか、匿名関数内から arguments.callええ 財産。

使用する方が良いです 名前付き関数 argument.callee より:

 function foo () {
     ... foo() ...
 }

よりも良い

 function () {
     ... arguments.callee() ...
 }

名前付き関数は、 発信者 財産:

 function foo () {
     alert(foo.caller);
 }

どちらが良いですか

 function foo () {
     alert(arguments.callee.caller);
 }

非推奨は現在の ECMAScript によるものです 設計原則.

ただの延長です。"this" の値は再帰中に変化します。次の (変更された) 例では、factorial は {foo:true} オブジェクトを取得します。

[1,2,3,4,5].map(function factorial(n) {
  console.log(this);
  return (!(n>1))? 1 : factorial(n-1)*n;
},     {foo:true}     );

初めて呼び出された階乗はオブジェクトを取得しますが、これは再帰呼び出しには当てはまりません。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top