Arguments.callee 已弃用 - 应该使用什么?

IT技术 javascript cross-browser
2021-01-19 17:01:30

对于做类似的事情

setTimeout(function () {
    ...
    setTimeout(arguments.callee, 100);
}, 100);

我需要类似的东西arguments.callee在 javascript.info找到arguments.callee已弃用的信息:

ECMA-262不推荐使用此属性,以支持命名函数表达式并提高性能。

但是应该用什么来代替呢?像这样的东西?

setTimeout(function myhandler() {
    ...
    setTimeout(myhandler, 100);
}, 100);
// has a big advantage that myhandler cannot be seen here!!! 
// so it doesn't spoil namespace

顺便说一句,arguments.callee跨浏览器兼容吗?

3个回答

是的,这就是理论上应该使用的。你说得对。但是,它一如既往地不适用于某些版本的 Internet Explorer。所以要小心。您可能需要依靠arguments.callee,或者更确切地说,是一个简单的:

function callback() {
    // ...
    setTimeout(callback, 100);
}

setTimeout(callback, 100);

哪个在 IE 上工作。

2021-03-18 17:01:30
等等 - 你想说这setTimeout(function myhandler() { setTimeout(myhandler ...在某些版本的 IE 中不起作用?这是非标准的事情吗?我认为这是一件非常标准的事情。
2021-04-01 17:01:30
@TomasT。:它标准的 - 但从什么时候开始 IE 成为完全标准的?:)(嗯,也许是 IE10。)我记得有一段时间被它绊倒了。快速测试表明它至少在 IE7 中不是问题。可能是IE6。我没有带它来测试。
2021-04-01 17:01:30
@lolzerywowzery:那arguments.callee不是命名函数表达式。IE、IIRC中的命名函数表达式分为三个时期:根本不工作,泄漏到周围范围内,按照规范工作。
2021-04-10 17:01:30

但是应该用什么来代替呢?像这样的东西?

是的,你回答了你自己的问题。有关更多信息,请参见此处:

为什么 JavaScript 中不推荐使用 arguments.callee.caller 属性?

关于为什么要进行此更改,它有一个很好的讨论。

minitech 的答案非常好,但它缺少另一种情况。你声明的函数叫做回调,这意味着两件事,一是函数是内存中的对象,二是函数名仅用于引用对象。如果您出于任何原因破坏了这两者之间的引用,则建议的代码也将不起作用。

证明:

function callback() {
    // ...
    setTimeout(callback, 100);
}

setTimeout(callback, 100);

var callback2 = callback; //another reference to the same object
callback = null; //break the first reference
callback2(); //callback in setTimeout now is null.

来自开发者 Mozilla 页面的描述是:

警告:ECMAScript (ES5) 第 5 版禁止在严格模式下使用 arguments.callee()。通过给函数表达式一个名称或在函数必须调用自身的地方使用函数声明,避免使用 arguments.callee()。

显然,这是第一个解决方法“通过给函数表达式命名”的示例,但让我们看看我们如何处理“或使用函数声明,其中函数必须调用自身”以及这会带来什么:

function callback(){
   //...
   setTimeout(innercall(), 100);
   function innercall(){
      //innercall is safe to use in callback context
      innercall.caller(); //this will call callback();
   }
}

然后我们可以安全地使用回调引用做任何我们想做的事情:

var callback2 = callback;
callback = null;
callback2(); //will work perfectly.
caller不是一个好习惯,这里的示例代码实际上似乎没有设置超时。只是不要覆盖您声明的函数。
2021-03-21 17:01:30