How does `arguments.callee` refer to anonymous functions?

前提是你 提交于 2019-12-23 02:07:08

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!