为什么Underscore.js有一个delay函数?

18

这是Underscore.js的delay函数的源代码:

_.delay = function (func, wait) {
    var args = slice.call(arguments, 2);
    return setTimeout(function () { return func.apply(null, args); }, wait);
};

这与setTimeout有何不同?为什么Underscore.js需要delay

4个回答

24

这是一种跨浏览器的方式,可以传递额外的参数,并将它们作为回调函数的参数出现,就像setTimeout()一样。在IE中无法使用该方法。

它可以使您的代码更加优美...

setTimeout(_.bind(function() { }, null, "arg1"), 1e3);

…对比…

_.delay(function() { }, 1e3, "arg1");

我认为这是Underscore方法中不太有用的一种,具体信息可以在Naomi的回答中找到。


1
Internet Explorer不支持回调参数。真是个麻烦事! - Aadit M Shah
@Alex - 它不支持将字符串字面量作为第一个参数传递,因此并非完全跨浏览器。也许在文档中有提到... - RobG
@alex,我认为这与跨浏览器兼容性没有任何关系。它只是一个方便函数,对于那些真正理解如何使用JavaScript的本机.bind.call.apply函数的人来说,它本身就没有什么意义。 - Mulan
1
@naomik,这怎么能说是无关呢?Underscore提供了(除其他功能外)一些在某些浏览器中缺失的功能。这里有另一个例子,它允许传递额外的参数到回调函数中。这在IE中是不支持的。这可能就是为什么这个函数存在的原因。 - alex
1
@naomik——我的任务不是思考为什么,只是进行评论。;-) 如果它只是一些简单的东西,比如 alert('boo'),那么我可能会将一个字符串传递给 setTimeout。但是我也可以这样做 setTimeout(Function('…'),…), 那么不支持字符串有什么好处呢? - RobG
显示剩余6条评论

17

为什么 Underscore.js 有一个延迟函数?

因为愚蠢。这个特定的 underscore.js 方法看起来很愚蠢。

缺点

  1. 库中的额外函数意味着较大的代码基础
  2. 更大的代码基础意味着需要维护的内容更多,可能会出现更多漏洞
  3. 使用此函数的代码现在依赖于该库
  4. 与本地API相比改进较小/无,成本收益比低
  5. 需要学习新API

优点

本节意围意让空白


我只是学习使用JavaScript并编写类似以下代码:

var hello = function() {
  console.log("hello");
};

var delay = 1000;

window.setTimeout(hello, delay);

简单吧?Underscore.js有时相当无用。老实说,window.setTimeout 就已经完全够用了。


这里是另一个例子,展示如何将参数传递给函数

var Cat = function(name) {
  function meow(message) {
    console.log(name, "says meow!", message);
  }
  this.meow = meow;
};

var duchess = new Cat("Duchess");

window.setTimeout(duchess.meow.bind(duchess, "please feed me!"), 2000);

// 2 seconds later
// => Duchess says meow! please feed me!
如果您无法依赖.bind,您也可以使用闭包。
window.setTimeout(function() {
  duchess.meow("please feed me!");
}, 1000);

哇,那真是太难了。我要回去使用underscore、lodash和jquery。这个JavaScript的东西太难了!


5
我理解你的方法,然而一旦你开始建立一个通用库,你很快会发现自己需要对所有东西进行包装,以免暴露底层API(例如,jQuery将所有东西都包装起来)。否则,用户会开始疑惑哪些是库里的,哪些是原生JS、DOM或者你正在抽象的其他内容。我并不支持一种方法胜过另一种,只是说说而已。 - RobG
3
一群新手仍在给这个投票负评。继续来吧,菜鸟 :) - Mulan
1
我不明白所有的仇恨。你不应该被踩。 - Aadit M Shah
3
我不同意@RobG的观点。我认为库的目标不应该是完全取代语言的所有本地功能。即使是实用程序库,它也应该专注于其实际改进的事物。在这种情况下,_.delay不足以成为一个(或者说完全不是)值得抽象和额外API记忆的改进。 - Mulan

10

aes·thet·ics

这个库的作者利用自己的业余时间开源、讲解并使用它,把它作为介绍JavaScript的一种方式,也许能够激发某些人对闭包作用域的兴趣,进而增强了这个库的吸引力。

仅就这个函数本身的相关性进行争论就像争论一幅画或其他工艺品的相关性。有些人可能喜欢它,而另外一些人可能不喜欢。

你可以喜欢或不喜欢它。我个人更喜欢那些直接点的库。

_.delay, _.defer, _.throttle, _.after 的流程在我看来读起来比window要更好。

此外,通常我也喜欢写node服务端代码(nodejs)而不必在模式之间切换......试试在node中使用window.timeout会发生什么。


4

其实没什么,只是它与deferdebounce等主题有关。这意味着您可以使用下划线包装符号:

_(yourfunction).delay(1000);

同时它似乎不会接受字符串参数,因为这会调用eval函数。

3
我认为任何理智的人都不会将一个字符串传递给 setTimeout 函数。 - Aadit M Shah
@plynx - 不一定使用 eval,它可能会使用 Function 构造函数。;-) @Aadit - 支持字符串也不难,只需测试第一个参数,如果是字符串,则使用 Function 构造函数,然后调用 set timeout。 - RobG
1
@AaditMShah robg,你们两个似乎都误解了我的意思——我指的是不接受字符串参数的好处。我经常看到这种情况发生,有时甚至是无意中发生的。在StackOverflow上的代码中可以找到许多例子。程序员的手有时很奇怪,有时候他们会在你不注意的时候给某些东西加上引号。 - Plynx
1
@Plynx - 我理解你的意思。我也明白 delay 更安全,因为你不能传递字符串参数。但我仍然认为,在正常情况下,没有人会把字符串传递给 setTimeout。你说,“程序员的手是奇怪的东西,有时候当你不注意时他们会在周围加上引号”,这让它听起来几乎像是个笑话。下次你看到那些手的工作,请告诉他们在玩危险游戏之前应该先咨询一下大脑。另外,在提到 @RobG 之前,你忘记在他名字前加上一个 at 符号了。 - Aadit M Shah
@AaditMShah 谢谢。我没有忘记,但是评论系统告诉我只能提及一个人,这对我来说似乎是一个奇怪的限制。至于没有理智的人会做这样的事情,这是一个学术论点。我可以说我同意你的观点,但这并不改变每天都有程序员为某种原因而这样做的事实,即使是那些知道避免在用户数据上使用 eval 的程序员,无论是由于 JS 语法不熟练还是支持旧代码等原因。因此,在 JavaScript 的严格模式下不允许这样做。 - Plynx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接