arguments.callee
是用来做什么的?它是如何工作的?它有哪些参数?
arguments.callee
是用来做什么的?它是如何工作的?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元素)。匿名函数在返回后会被垃圾回收,但在这种情况下,我将其添加到超时回调的作用域中(将其作为参数传递给另一个返回实际回调函数的匿名函数),因此它仍然被某处引用。
现在,如果您使用严格模式,您不必担心,因为代码在严格模式下看起来像这样:
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引用,这可能导致内存泄漏。
实际上:这里有另一个真实的例子,其中使用了 arguments.callee
:事件委托和分离事件侦听器
这里有关于JS严格模式和使用arguments.callee
的递归的更多信息。
最后一个问题,我认为最明显的例子是: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 已被弃用的原因)
同时还有更多关于严格模式的内容
它指定了当前正在执行的函数,因此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)
arguments.callee是一种通过询问“谁在调用这个特定参数?”来知道当前执行函数的迂回方式。. . . .
function factorial(a){
if(a>0)
return a*arguments.callee(a-1);
}
arguments.callee
是一个自身的 function
function init(name){
if(name != ""){
console.log('name',name)
}else{
console.log('type', typeof arguments.callee) // function
console.log("who am i :\n", arguments.callee)
arguments.callee('john')
}
}
init("")
callee
的不良使用。给函数命名并使用该名称调用它会更好,也更不容易出错。 - Mathias Schwarzarguments.callee
时期望哪些参数,而arguments.callee.length
会告诉你这一点。奇怪的是,没有人指出这一点:跨浏览器是没问题的,即使IE8也支持,但是请注意:在严格模式下会抛出错误。 - Elias Van Ootegem