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

小提琴按预期工作,但我很好奇它是否真的是一遍又一遍地调用同一个函数,或者是否有多个对调用的原始函数的引用,或者是否有多个相同的函数被调用......毕竟,没有命名做了参考,那么随着遍历的深入,它将如何工作?我想我可以通过将以下代码添加到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

我真的一遍又一遍地调用同一个函数,还是调用了多个相同的函数,或者还有其他东西在起作用?

是的,你只有一个函数实例,你一直引用它。但是,您正在设置一个调用堆栈,其中D将为每次调用保存局部变量(在您的情况下为参数)。

为什么 arguments.caller 不指向我们的函数?

对象上没有caller属性arguments,它已被删除。您可能指的是函数对象的caller属性,它是非标准的但仍然可用(尽管在严格模式和argments.callee.

于 2012-09-18T13:11:29.060 回答
1

这里只涉及一个函数实例。该函数递归调用自身。您可以通过为代码中的函数表达式指定名称来轻松检查这一点:

(function fn (D) {

然后,在体内:

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

上述对于每次调用都是正确的,表明在此过程中只创建和调用了一个函数。

另外,这个:

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

向您展示该函数调用自身,即调用者是被调用者。上述表达式对于除第一个调用之外的每个调用都是正确的,因为第一次调用发生在全局代码中。

现场演示:http: //jsfiddle.net/HbThh/2/

于 2012-09-18T14:12:33.193 回答
0

没有你应该用来获取的caller属性。argumentsarguments.callee.callercaller

于 2012-09-18T12:56:37.757 回答