如何缩短我的条件语句

IT技术 javascript if-statement
2021-03-01 22:25:19

我有一个很长的条件语句,如下所示:

if(test.type == 'itema' || test.type == 'itemb' || test.type == 'itemc' || test.type == 'itemd'){
    // do something.
}

我想知道是否可以将此表达式/语句重构为更简洁的形式。

关于如何实现这一目标的任何想法?

6个回答

将您的值放入一个数组中,并检查您的项目是否在数组中:

if ([1, 2, 3, 4].includes(test.type)) {
    // Do something
}

如果您支持的浏览器没有该Array#includes方法,您可以使用这个 polyfill


~波浪号快捷方式的简短说明

更新:既然我们现在有了这个includes方法,就没有必要~使用hack 了。只是将它保留在这里,供那些有兴趣了解它是如何工作的和/或在其他代码中遇到过它的人使用。

除了检查indexOfis的结果之外>= 0,还有一个不错的小捷径:

if ( ~[1, 2, 3, 4].indexOf(test.type) ) {
    // Do something
}

这是小提琴:http : //jsfiddle.net/HYJvK/

这是如何运作的?如果在数组中找到一项,则indexOf返回其索引。如果未找到该项目,它将返回-1在不涉及太多细节的情况下, the~是一个按位非运算符,它将0返回for -1

我喜欢使用~快捷方式,因为它比对返回值进行比较更简洁。我希望 JavaScript 有一个in_array直接返回布尔值函数(类似于 PHP),但这只是一厢情愿的想法(更新:现在有了。它被称为includes。见上文)。请注意 jQuery 的inArray,虽然共享 PHP 的方法签名,但实际上模仿了本机indexOf功能(这在不同情况下很有用,如果索引是您真正想要的)。

重要说明:使用波浪号快捷方式似乎充满争议,因为有些人强烈认为代码不够清晰,应该不惜一切代价避免使用(请参阅对此答案的评论)。如果你同意他们的观点,你应该坚持.indexOf(...) >= 0解决方案。


稍微长一点的解释:

JavaScript 中的整数是有符号的,这意味着最左边的位被保留为符号位;指示数字是正数还是负数的标志,a1为负数。

以下是一些 32 位二进制格式的示例正数:

1 :    00000000000000000000000000000001
2 :    00000000000000000000000000000010
3 :    00000000000000000000000000000011
15:    00000000000000000000000000001111

现在这里是相同的数字,但为负数:

-1 :   11111111111111111111111111111111
-2 :   11111111111111111111111111111110
-3 :   11111111111111111111111111111101
-15:   11111111111111111111111111110001

为什么负数的组合如此奇怪?简单的。负数只是正数 + 1 的倒数;将负数添加到正数应该总是 yield 0

为了理解这一点,让我们做一些简单的二进制算术。

以下是我们将如何添加-1+1

   00000000000000000000000000000001      +1
+  11111111111111111111111111111111      -1
-------------------------------------------
=  00000000000000000000000000000000       0

这是我们将如何添加-15+15

   00000000000000000000000000001111      +15
+  11111111111111111111111111110001      -15
--------------------------------------------
=  00000000000000000000000000000000        0

我们如何得到这些结果?通过定期加法,我们在学校教的方式:你从最右边的列开始,然后把所有的行加起来。如果总和大于最大的一位数(十进制为9,二进制为1),我们将余数转移到下一列。

现在,您会注意到,当将负数与正数相加时,并非全为0s的最右侧列将始终有两个1s,将它们加在一起将导致2. 两个是 的二进制表示10,我们将1带到下一列,并将0结果放在第一列中。左边的所有其他列只有一行带有 a 1,因此1从前一列结转的值将再次加起来为2,然后结转......这个过程会不断重复,直到我们到达最左边的列,其中在1被结转无处可去,所以它溢出和丢失,我们就只剩下0一切都跨越。

这个系统被称为2的补码您可以在此处阅读有关此内容的更多信息:

2 的有符号整数的补码表示


既然 2 的补码的速成课程已经结束,您会注意到这-1是唯一一个二进制表示为1's all的数字。

使用~按位非运算符,给定数字中的所有位都被反转。0从反转所有位回来的唯一方法是,如果我们从1's allcross 开始。

所以,所有这些都是一种冗长的说法,~n只有0nis时才会返回-1

技术很好,但我不喜欢它。乍一看不清楚代码在做什么,这使得它无法维护。我更喜欢“Yuriy Galanter”的回答。
2021-04-18 22:25:19
-1 由于在一种语言中进行了不必要的位调整,而这种语言一开始并没有真正指定很多关于位表示的内容。另外,这个答案的大部分内容都是在解释这个问题。如果你必须写 20 段来解释 hack,它真的可以节省时间吗?
2021-04-18 22:25:19
-1 新程序员看到这样的答案,认为这是一种很酷且可接受的编码方式,然后在 5 年内我必须维护他们的代码并撕掉我的头发
2021-05-04 22:25:19
虽然使用按位运算符确实很吸引人,但它真的比!== -1以任何可以想象的方式更好吗?显式布尔逻辑不是比隐式使用零假更合适吗?
2021-05-11 22:25:19
这种习惯用法在 C#、Java 或 Python 等语言中绝对不常见,这些都是我的专业领域。我只是问了这里的一些当地 Javascript 专家,他们之前没有人见过它;所以它显然不像你声称的那么普遍。 应该始终避免使用更清晰和更常见的方式!= -1
2021-05-14 22:25:19

您可以使用带有 fall thru 的 switch 语句:

switch (test.type) {

  case "itema":
  case "itemb":
  case "itemc":
  case "itemd":
    // do something
}
和if基本一样,数组方法的index要好很多
2021-04-18 22:25:19
我知道这个答案必须在这里,但我不得不向下滚动到底部才能找到它。这正是 switch 语句的设计目的,并适用于许多其他语言。我发现很多人不知道 switch 语句中的“fall through”方法。
2021-04-21 22:25:19
我认为如果你有很多条件,在一个方法中编写会很糟糕......如果有几个条件可以,但对于超过 10 个,我会去使用数组来保持代码整洁。
2021-04-22 22:25:19
@kojiro 可悲的是,正确的答案是这个,但不可能引起人们的注意,而不是令人敬畏的位数组技巧。
2021-05-06 22:25:19
此解决方案在 Firefox 和 Safari 上是最快的,||在 Chrome 上是第二快的(仅次于原始解决方案)。请参阅jsperf.com/if-statements-test-techsin
2021-05-07 22:25:19

使用科学:你应该按照 idfah 所说的去做,这样可以在保持代码简短的同时获得最快的速度:

这比~方法更快

var x = test.type;
if (x == 'itema' ||
    x == 'itemb' ||
    x == 'itemc' ||
    x == 'itemd') {
    //do something
}

http://jsperf.com/if-statements-test-techsin 在此处输入图片说明 (上集:Chrome,下集:Firefox)

结论 :

如果可能性是少数,你知道,某些是更有可能比你得到最大的性能出去发生if ||switch fall throughif(obj[keyval])

如果可能性有很多,并且其中任何一个都可能是最常发生的,换句话说,您无法知道哪一个最有可能发生,而不是从对象查找中获得最大的性能if(obj[keyval])以及regex是否合适。

http://jsperf.com/if-statements-test-techsin/12

如果有新东西出现,我会更新。

+1 一个非常好的帖子!如果我理解正确,这switch case是最快的方法?
2021-04-16 22:25:19
在 Firefox 中是的,在 chrome 中 if ( ...||...||...)...
2021-04-20 22:25:19
@Mich 不要为了速度而牺牲代码的优雅。这是很多很多人都会对你说的话。最后,只是使用常识。
2021-05-02 22:25:19
如果你真的对这个输入进行多次循环,它会更快,但如果你有一个包含非常大的 n(“itemX”字符串的数量)的循环,慢得多。我修改了这个代码生成器,你可以用它来验证(或者反驳)。obj["itemX"]如果 n 很大,则非常快。基本上,什么速度快取决于上下文。玩得开心。
2021-05-10 22:25:19
所以这是最快的方法,但这重要吗?
2021-05-12 22:25:19

如果您要与字符串进行比较并且存在模式,请考虑使用正则表达式。

否则,我怀疑试图缩短它只会混淆你的代码。考虑简单地包裹线条以使其漂亮。

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}
这个答案是速度方面的赢家 jsperf.com/if-statements-test-techsin
2021-04-16 22:25:19
当项目进入维护模式时,这也是最容易扩展的(使用规则,例如,(test.type == 'itemf' && foo.mode == 'detailed')
2021-04-24 22:25:19
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) { … }

使用对象作为关联数组是很常见的事情,但由于 JavaScript 没有本地集,您也可以将对象用作廉价集。

但你可以这样做: if(possibilities[test.type]) 并保存整整 2 个字符!:)
2021-04-17 22:25:19
这比 FlyingCat 试图缩短的正常 if 语句短多少?
2021-05-03 22:25:19
if如果删除所有空格,@dcarson OP语句的条件需要 78 个字符。如果你这样写,我的需要 54: test.type in {"itema":1,"itemb":1,"itemc":1,"itemd":1}从根本上说,对于每个额外的密钥,他每使用两个地雷就使用四个字符。
2021-05-16 22:25:19