【问题标题】:Javascript arguments.callee what is it forJavascript arguments.callee 它有什么用
【发布时间】:2012-08-21 07:32:40
【问题描述】:

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

arguments.callee 是干什么用的?它是如何工作的?

它有哪些参数?

【问题讨论】:

  • 其他人注意到 arguments.callee 是什么(并指出了 MDN,它对此主题有很好的描述) - 您可以使用 arguments.callee 的内容是在一个调用自身的递归函数中。
  • 这(连同所有其他内容)是对callee 的不当使用。给函数一个名字并使用这个名字来调用它会更好,也不会那么脆弱。
  • if by "which arguments does it have" 你的意思是:它期望哪些参数,答案是:函数 "expect" 哪些参数i> 您在其中使用arguments.calleearguments.callee.length 会告诉您这一点。奇怪的是没有人指出这一点:X-browser,当然;甚至 IE8 也支持它,但是:小心严格模式它会抛出错误

标签: javascript anonymous-function


【解决方案1】:

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

但是,我个人 - 和 I'm not alone in this- 我会想念这个属性。在我解释原因之前,我会给你一个伪例子,说明你什么时候可以使用它:

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'编。这可能会导致循环引用,更糟糕的是,循环 DOM 引用会导致内存泄漏。

实际上:here's another, real example 使用 arguments.callee 的地方:事件委托和分离事件侦听器
here's some more info 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 已被弃用的原因)
more on strict

【讨论】:

  • @JordiP.S.:我的答案底部添加了 2 个链接,都是 MDN
  • 答案在 getElementById('foobar') 之后的第一个代码块末尾缺少右括号
  • @Frug:已编辑,我可以补充一下:很好。我还更改了 IIFE,将调用括号移动到分组运算符中
【解决方案2】:

它指定了当前正在执行的函数,所以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)

【讨论】:

    【解决方案3】:

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

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

    【讨论】:

      【解决方案4】:

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

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

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

      这是一个很好的参考

      arguments.callee from MDN

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

      【讨论】:

        【解决方案5】:

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

        MDN docs here

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-06-17
          • 2012-01-11
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-14
          • 2013-10-13
          • 1970-01-01
          相关资源
          最近更新 更多