需要一个脚本来快速告诉我页面上有多少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按预期工作,但我很好奇它是否真的是相同的函数一遍又一遍地调用,或者是否有多个对原始函数的引用,或者有多个相同的函数叫做...毕竟,没有命名引用,所以当遍历更深入时它会如何工作?我想我可以通过将the following code添加到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
不指向我们的功能?它显然被它调用 - 这就是递归的工作原理,不是吗?
答案 0 :(得分:1)
我是不是一遍又一遍地调用同一个函数,或者是否有多个相同的函数被调用或者还有其他什么在起作用?
是的,您只有一个函数实例,您始终可以引用它。但是,您正在设置一个调用堆栈,其中将为每次调用保存局部变量(在您的情况下为参数D
)。
为什么arguments.caller没有指向我们的函数?
caller
对象上没有arguments
属性,它是removed。你可能意味着函数对象的caller
property,它是非标准的但仍然可用(虽然在严格模式和argments.callee
中都被禁止)。
答案 1 :(得分:1)
这里只涉及一个函数实例。该函数以递归方式调用自身。您可以通过在代码中为函数表达式指定名称来轻松检查:
(function fn (D) {
然后,在体内:
fn === arguments.callee // => true
每次调用都是如此,表明在此过程中只创建并调用了一个函数。
另外,这个:
arguments.callee === arguments.callee.caller // => true, except first time
显示函数调用自身,即调用者是被调用者。除了第一个调用之外,上面的表达式适用于每个调用,因为第一次调用是从全局代码发生的。
答案 2 :(得分:0)
caller
没有arguments
属性,您应使用arguments.callee.caller
获取caller
。