28

我还没有找到这个变量的任何完整的跨浏览器文档。

arguments.callee为了什么?它是如何工作的?

它有哪些论据?

4

5 回答 5

31

arguments.callee是对当前正在调用的函数的引用。首先要做的事情:不要使用它:如果您处于严格的上下文中,它只会喷出错误。

然而,就个人而言——而且我并不孤单——我会想念这处房产。在我解释原因之前,我会给你一个伪示例,说明何时可以使用它:

var looper = (function(someClosureVar)
{
    setTimeout((function(resetTimeout)
    {
        return function()
        {
            //do stuff, stop OR:
            resetTimeout();
        };
    }(arguments.callee)),1000);
}(document.getElementById('foobar')));

我希望你喜欢闭包,因为我喜欢 - 这arguments.callee就是很可能发生的地方。倒数第二行是钱的位置:

(arguments.callee)

是对在闭包范围内设置初始超时的匿名函数的引用(在这种情况下,它可以访问 1 个 DOM 元素)。匿名函数在返回后会被 GC,但在这种情况下,我已将其添加到超时回调的范围内(将其作为参数传递给另一个返回实际回调的匿名函数),因此它仍然在某处被引用。
现在,如果您是严格模式,则不必担心,因为这是严格模式下的代码:

var looper = (function tempName(someClosureVar)
{
    setTimeout((function(resetTimeout)
    {
        return function()
        {
            //do stuff, stop OR:
            resetTimeout();
        };
    }(tempName)),1000);
}(document.getElementById('foobar')));

命名函数,就是这样。为什么我不喜欢它?arguments.callee引发标志,就像一些闭包诡计正在发生的匿名函数一样。我想这只是一种习惯,但我觉得它可以帮助我更轻松地构建和调试我的代码。
再加上对 IE 的病态仇恨,这对于任何做一些客户端脚本的人来说都是很自然的。不支持严格模式的 IE 版本倾向于将函数名称泄漏到全局命名空间,因此永远不允许与函数(以及我们创建的闭包)关联的内存被 GC'ed。这可能会导致循环引用,更糟糕的是,循环 DOM 引用会导致内存泄漏。

实际上:这是另一个使用位置的真实示例arguments.callee:事件委托和分离事件侦听器
这里有更多关于 JS 严格模式和递归使用的信息arguments.callee

最后一个问题是,IMO 是如何方便的最清晰的例子arguments.callee:递归替换函数:

function someF(foo)
{
    //'use strict'; <-- would throw errors here
    foo = foo.replace(/(a|b)+/gi, function (p1,p2)
    {
        if (p1.match(/(a|b){2,}/i))
        {
            return p1.replace(/(a|b)/gi,arguments.callee);//recursive
        }
        return (p2.match(/a/i) ? 'X':'Y');
    });
}

正如 MDN 上要求的arguments.callee,在严格模式下使用警告(ECMA 5,这解释了为什么 DC 说 arguments.callee 已被弃用)
以及更多关于严格的

于 2012-08-21T08:30:16.650 回答
5

它指定当前执行的函数,arguments.callee当前函数也是如此。如果您需要在匿名函数中递归,这可能会有所帮助。这里是来自 Mozilla 的示例:

function create() {
   return function(n) {
      if (n <= 1)
         return 1;
      return n * arguments.callee(n - 1);
   };
}

var result = create()(5); // returns 120 (5 * 4 * 3 * 2 * 1)
于 2012-08-21T07:41:22.870 回答
4

Calee 是 ECMAScript 3 标准的一部分,因此跨浏览器使用应该是安全的。被调用者持有当前正在执行的函数,调用它将调用当前函数。因此,被调用者采用与封闭函数完全相同的参数(或者更确切地说,它当前函数)。此处提供了更多信息:https ://developer.mozilla.org/en-US/docs/JavaScript/Reference/Functions_and_function_scope/arguments/callee

使用被调用者被认为是不好的风格。给你函数一个名字,然后使用这个名字......

于 2012-08-21T07:38:47.877 回答
3

arguments.callee 是一种通过询问“谁在调用这个特定参数?”来了解当前执行函数的方法。. . . .

 function factorial(a){
    if(a>0)
      return a*arguments.callee(a-1);
 }

在这里,如果你调用 factorial(5),它将检查条件是否大于 0,如果为真,将对下一个较小的数字执行相同的逻辑。. . 在某些情况下,您不知道要调用的函数的名称。. . .所以你可以使用这个属性

这是一个很好的参考

来自 MDN 的 arguments.callee

更新: arguments.callee()在 ES5 中已弃用

于 2012-08-21T07:42:37.613 回答
2

callee 是 arguments 对象的属性。它可用于引用该函数的函数体内当前正在执行的函数。

MDN 文档在这里

于 2012-08-21T07:38:42.710 回答