是否有充分的理由将字符串传递给 setTimeout?

IT技术 javascript settimeout
2021-01-13 00:52:20

我们都知道将字符串传递给setTimeout(or setInterval) 是邪恶的,因为它在全局范围内运行,存在性能问题,如果您正在注入任何参数等,则可能不安全。因此,绝对不推荐这样做:

setTimeout('doSomething(someVar)', 10000);

赞成:

setTimeout(function() {
    doSomething(someVar);
}, 10000);

我的问题是:有没有理由做前者?曾经是可取的吗?如果不是,为什么它甚至被允许?

我想到的唯一场景是想要使用存在于全局作用域中但已在局部作用域中被覆盖的函数或变量。对我来说,这听起来像是糟糕的代码设计,但是......

2个回答

您始终可以通过将它们作为 window 对象的属性访问来使用全局变量,例如window.globalVar(尽管使用全局变量确实不是一个好习惯),所以不,我认为没有充分的理由使用已弃用的语法。

由于历史原因,可能允许这样做:正如 Felix Kling 所提到的,原始语法只允许传递一串代码:

在 JavaScript 1.0、Netscape 2.0 中引入。JavaScript 1.2、Netscape 4.0 引入了传递函数对象引用MSHTML DOM 从 5.0 版开始支持。[来源,我的重点]

如果浏览器不再支持使用字符串作为setTimeoutand 的第一个参数,setInterval互联网上将有大量代码不再起作用。

@472084 是的,癌症应该被治愈。
2021-03-12 00:52:20
从 SO 上使用字符串的示例数量来看……不幸的是,这是非常正确的。
2021-03-27 00:52:20

对于那些被为什么传递函数比传递字符串更好的问题重定向到这里的人

1:传递一个字符串会启动一个编译器

每次必须对字符串求值时,都会启动一个完整的编译器。对于每一个需要的调用。

这不仅很慢,而且会破坏所有已完成的 JIT 和浏览器加速。

2:传递字符串的限制要大得多。

因为字符串是通过编译器运行的,所以它并没有完全绑定到局部作用域和变量。

虽然在以下情况下不明显:

window.setInterval("doThing()");

在更复杂的情况下,代码更简洁:

window.setInterval("doThing(" + val1 + "," + val2 + ")");

对比

window.setInterval(function() {
  // You can put a debugging point here
  dothing(val1, val2);
});

3:DOM对象不能通过字符串传递

正如 Álvaro 所提到的,DOM 对象不能通过字符串方法传递。

// There is no way to do this via a string.
var el = document.getElementById("my-element");
window.setInterval(function() {
  dothing(el);
});

(其他对象可能会或可能不会通过——取决于它们是否可以被序列化,但一般来说这将是相当困难的。)

@ÁlvaroG.Vicario 啊是的!优秀的。我会补充的。
2021-03-12 00:52:20
更不用说何时需要将对象作为参数传递(DOM 节点、日期...)。
2021-03-22 00:52:20