治疗零的模式作为truthy

时间:2013-07-02 19:11:07

标签: javascript node.js

我经常做这样的事情:

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个洞,这是智能可读的:如果我们有一个字符串使用它,否则使用defaut。

或者这条路线:

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,因为我很少使用有意识地对待nullundefined的JS代码。我觉得保持这种状态会更好。
  • 我觉得NaN应该转到24,因为这更接近||模式。虚假的东西应该是默认的。
  • 'abc'应该转到24 - 在我的实际应用中,这是用户输入,用户不应该错误地输入,比如电子邮件。
  • 理想情况下,
  • '123abc'应转到24,转换为Number捕获但parseInt不转换。我相信电子邮件可以从数字开始,所以这可以说明这是应该被抓住的东西。

可以接受下划线或者Lodash答案,,特别是对于那些教我试图“聪明”而不是写2-3行功能的人。这些库的存在正是因为有许多简单的2-3行函数在世界各地的许多代码库中的许多地方完成同样的事情,并且它具有更高的可读性和可维护性以及将它们隔离为类似的东西,比如{ {1}}。如果不存在这样的方法并且我能够提出足够的一般要求,我将自己提交一个民意调查请求并将其作为这个问题的答案发布。这是我喜欢JS的东西 - 它具有良好的生态系统,因为很可能必须编写这些实用程序方法。由于我特别处理用户输入,因此我可能更好地编写一个稍微更专业的函数并提交给commander.js,这是我一直需要它的地方。

5 个答案:

答案 0 :(得分:4)

提到int一个要求,所以假设你想要任何号码,否则默认为24,你可以使用:

delay = isFinite(delay) ? delay : 24;

或更安全:

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

或罗伯特柠檬特别:

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

当然让其他人一眼就能理解这句话比语法糖更重要。你正在编写代码以供人和机器理解,而不是为了抵御工业间谍。

答案 1 :(得分: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
}

不要试图滥用该语言。不要试图聪明。不要试图模糊你的代码。它不会为你的自我服务,也会损害你代码的可维护性和可读性。

有功能,可以有名字。它们完全是为了您正在寻找的目的:给一些指令命名。使用它们。

答案 2 :(得分:1)

假设用户输入正如某些评论所说,那么它从任何可能的字符串开始,所以也可以测试它。

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

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

答案 3 :(得分: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”,因为它是一个真正的价值。

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

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

答案 4 :(得分:0)

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

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

我认为它会破坏其他脚本,但如果我们可以在javascript中的块级别执行此类操作,那就太好了...