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