1

ページにある HTML コメントの数とその内容をすばやく通知するスクリプトが必要でした。再帰的な DOM トラバーサルに無名関数を使用することは適切に思えました。

var comments = []; //set up an array where comment contents will be copied to

(function(D) {
  if (8===D.nodeType) comments.push(D.nodeValue); //check if node is a comment
  D=D.firstChild;
  while (D) {
    arguments.callee(D); //recursively look for comments...
    D=D.nextSibling; //...and remember to iterate over all children of any node
  }
})(document);

console.log(comments.join("\r\n")); //list all comments

Fiddleは期待どおりに動作しますが、本当に同じ関数が何度も呼び出されたのか、元の関数への複数の参照が呼び出されたのか、それとも同じ関数が複数呼び出されたのか、興味がありました...参照が行われたので、トラバーサルが深くなるにつれてどのように機能しますか? 次のコードを追加することで確認できると思いましたwhile (D) {...}

//tmpCallee has been declared
if (tmpCallee) {
  console.warn(arguments.callee === tmpCallee);//true
  /*great, means these should be both pointing to the same function*/
  console.log(arguments.callee === arguments.caller);//false
  /*wait, what? didn't we just establish above that 
    all of our functions called recursively would be the same?*/
  console.log(arguments.caller);//undefined... but it was called recursively!
  console.log(arguments.callee);//prints our function code verbatim as it should
}
tmpCallee = arguments.callee;

よくわかりません。1)私は本当に同じ関数を何度も呼び出していますか、それとも複数の同一の関数が呼び出されていますか、それとも他の何かが働いていますか?2)関数を指していarguments.caller ないのはなぜですか? それは明らかにそれによって呼び出されました-それが再帰の仕組みですよね?

4

3 に答える 3

1

私は本当に同じ関数を何度も呼び出していますか、それとも複数の同じ関数が呼び出されていますか、それとも何か他のものが働いていますか?

はい、常に参照している関数インスタンスは1つだけです。ただし、呼び出しスタックを設定しているDため、呼び出しごとにローカル変数(この場合は引数)が保存されます。

なぜarguments.callerが関数を指さないのですか?

オブジェクトにcallerプロパティはありません。削除されました。あなたはおそらく関数オブジェクトのプロパティを意味していました。これは非標準ですが、それでも使用可能です(ただし、厳密モードでも禁止されています)。argumentscallerargments.callee

于 2012-09-18T13:11:29.060 に答える
1

There is only one function instance involved here. That function is calling itself recursively. You can easily check this by assigning a name to the function expression in your code:

(function fn (D) {

and then, inside the body:

fn === arguments.callee // => true

The above will be true for every invocation, showing that only one function was created and invoked in this process.

Also, this:

arguments.callee === arguments.callee.caller // => true, except first time

shows you that the function invokes itself, i.e. the caller is the callee. The above expression is true for every invocation, except the first one, since the first invocation occurred from global code.

Live demo: http://jsfiddle.net/HbThh/2/

于 2012-09-18T14:12:33.193 に答える
0

を取得するために使用するcallerプロパティはありません。argumentsarguments.callee.callercaller

于 2012-09-18T12:56:37.757 に答える