问题
A script was needed to quickly tell me how many html comments there are on the page and what their contents are. Using an anonymous function for recursive DOM traversal seemed appropriate:
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 works as expected, but I was curious if it was really the same function called over and over, or were there multiple references to the original function called, or were there multiple identical functions called... After all, there has been no named reference made, so how would it work as the traversal goes deeper? I thought I may be able to check that by adding the following code into 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;
I'm confused. 1) am I really calling the same function over and over or are there multiple identical functions called or is something else at play? 2) why does arguments.caller
not point at our function? it was clearly invoked by it - that's how recursion works, no?
回答1:
am I really calling the same function over and over or are there multiple identical functions called or is something else at play?
Yes, you have only one function instance, which you refer to all the time. However, you are setting up a call stack in which local variables (in your case the argument D
) would be saved for every invocation.
why does arguments.caller not point at our function?
There is no caller
property on the arguments
object, it was removed. You probably meant the caller property of the function object, which is non-standard but still usable (although forbidden in strict mode as well as argments.callee).
回答2:
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/
回答3:
There is no caller
property for arguments
you should use arguments.callee.caller
to get caller
.
来源:https://stackoverflow.com/questions/12477115/how-does-arguments-callee-refer-to-anonymous-functions