5

我经常做这样的事情:

delay = delay || 24; // default delay of 24 hours

但我实际上想允许 0 和0 || 24 === 24,而不是0

我想知道最好的模式是从命令行获取用户输入,或者从任何地方输入,并执行相同的逻辑,只将零视为真实。我认为我发现的最佳模式就是这样做:

delay = (delay === 0 ? delay : (delay || 24));

首先,它允许诸如 之类的东西'abc',这确实是错误的。但是,如果我提早输入+,它就会null滑过,这也是错误的。其次,非常难看,因为它显然是在解决语言缺陷,而不是使用可用的语言工具做一些优雅的事情。而且可读性不强。我正在做的事情是一种思路,我想用一行实际的代码来做(而不是技术性的一行,就像这样)。但我的大多数其他想法变得更加丑陋:

delay = typeof delay === 'number' ? delay : 24; // but typeof NaN === 'number', so
delay = (!isNaN(delay) && typeof delay === 'number') ? delay : 24;

请注意,这实际上适用于字符串 - 如果我有兴趣接受"",那么

str = typeof str === 'string' ? str : 'default';

因为没有NaN洞,这是智能可读的:如果我们有一个字符串,使用它,否则使用默认值。

或者这条路线:

delay = !isNaN(+delay) ? delay : 24; // fails on null
delay = !Number.isNaN(+delay) ? delay : 24; // still fails on null
// same thing with null check, now way uglier than we started

所以我还是更喜欢我的 hacky 三元和布尔逻辑。是的,我正在寻找一种简洁的、单行的解决方案,因为 JS 充满了模式,而且在许多其他语言中聪明的东西在 JS 中得到了很好的认可、可读性和清晰性。但我是新手并试图学习好的模式,因此,这个问题。

为了更明确的要求:

  • 0需要去0
  • undefined需要去24
  • 所有实际数字typeof都需要自己去,除了NaN.
  • 我强烈觉得null应该去,24因为我很少使用故意区别对待的 JSnull代码undefined。我觉得最好保持这种状态。
  • 我觉得NaN应该去,24因为这更接近||模式。虚假的东西应该默认。
  • 'abc'应该转到 24 - 在我的实际应用程序中,这是用户输入,用户不应该错误地输入,比如电子邮件。
  • '123abc'理想情况下应该转到24,转换为Number捕获但parseInt没有。我相信电子邮件可以以数字开头,所以这让我们明白这是应该被抓住的东西。

下划线或 lodash 的答案是可以接受的, 特别是对于那些教导我尝试“聪明”而不是编写 2-3 行函数的人。这些库的存在正是因为在世界各地的许多代码库中的许多地方都有许多简单的 2-3 行函数完成相同的事情,并且将它们隔离为诸如_.readNumber. 如果不存在这样的方法并且我能够提出足够一般的要求,我将自己提交一个投票请求并将其发布为这个问题的答案。这是我喜欢 JS 的一点——它有很好的生态系统,因为它很可能必须编写这些实用方法。由于我特别处理用户输入,因此编写一个稍微更专业的函数并提交给commander.js 可能会更好,这正是我一直需要的地方。

4

5 回答 5

4

没有int提到任何要求,所以假设你想要任何数字,否则默认为 24​​,你可以使用这个:

delay = isFinite(delay) ? delay : 24;

或者更安全:

delay = isFinite(parseFloat(delay)) ? delay : 24;

或者罗伯特柠檬特别:

delay = isFinite(parseFloat(delay))|0||24;

当然,让别人一眼就能理解语句比语法糖更重要。你编写的代码是为了让人和机器都能理解,而不是为了抵御工业间谍。

于 2013-07-02T19:34:12.487 回答
4

迄今为止最干净的解决方案:

delay = numberOrDefault(delay, 24);

// i = i || 24 doesn't work with i = 0, so this small func takes care of this.
function numberOrDefault(input, default) {
    // a few lines handling your case
}

不要试图滥用语言。不要试图变得聪明。不要试图混淆你的代码。它只会服务于你的自我,并且会损害代码的可维护性和可读性。

函数在那里并且可以有名字。它们完全是为了您正在寻找的目的而完成的:为一些指令命名。使用它们。

于 2013-07-02T19:48:02.870 回答
1

假设用户输入如某些评论所说,那么它以任何可能的字符串开头,因此不妨对其进行测试。

delay = /^(\d+)$/.exec( delay ) ? Number( RegExp.$1 ) : 24;

请注意,这也可以防止负整数,尽管没有作为要求给出,但作为时间延迟是荒谬的。

于 2013-07-02T19:38:57.443 回答
0

怎么样:

delay = isNaN(parseInt(delay, 10)) ? 24 : delay

(编辑:我现在在评论中看到了这个建议。老实说,这是我在控制台中解决这个问题时发生的。:D)

如果您绝对要求带有前导数字的字符串无效,则必须对其进行类型检查:

delay = typeof(delay) === "number" && isNaN(parseInt(delay, 10)) ? 24 : delay

例如,如果我使用你的成语:

delay = (delay === 0 ? delay : (delay || 24));

而“延迟”是“123abc”,你的方法会导致延迟仍然是“123abc”,因为它是一个真实的值。

根据 Shmiddty 的评论,如果您不打算进行显式类型检查,则需要使用 parseInt 来确保您实际设置delay为整数类型;即使 0 是真实的,如果在没有任何强制或类型检查的情况下通过,doingdelay = delay || 24也会设置为字符串值。delay在执行 isNaN 检查之前强制转换为数字可确保任何不是有效数字(由 parseInt 解析;带有前导数字的字符串仍会溜走)确保当您检查时isNaN,结果将意味着“这是一个有效数字”或“这不是一个有效的数字”,而不是“这是 NaN”或“这是除 NaN 之外的任何东西”。

如果您正在执行类型检查,您并不严格需要 parseInt,但我认为从语义角度来看它仍然是一个好主意,因为它表明您期望并需要该值的整数。

于 2013-07-02T19:25:28.240 回答
0

不要这样做,即使它可以完全按照你的意愿做:

Number.prototype.valueOf=function(){return this||"0";}
alert(  0 || 24 )// shows: 24

我认为它会破坏其他脚本,但如果我们可以在 javascript 的块级别上做这样的事情会很好......

于 2013-07-02T20:09:47.293 回答