如何缩短我的条件陈述

2020/11/05 19:02 · javascript ·  · 0评论

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

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

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

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

将您的值放入数组,然后检查您的项目是否在数组中:

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

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


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

更新:由于我们现在有了includes方法,因此~不再需要使用hack。只是将其保存在这里,以供有兴趣了解它的工作原理和/或在他人的代码中遇到过它的人使用。

除了检查结果是否indexOf为之外>= 0,还有一个不错的捷径:

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

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

这是如何运作的?如果在数组中找到一个项目,则indexOf返回其索引。如果找不到该项目,它将返回-1无需赘述,~按位NOT运算符,该运算符0返回-1

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

重要说明:使用波浪号快捷方式似乎引起了争议,因为有些人强烈地认为代码不够清晰,应该不惜一切代价避免使用(请参阅此答案的注释)。如果您有共同的想法,则应该坚持.indexOf(...) >= 0解决。


稍长一点的解释:

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

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

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

现在,这些数字相同,但为负数:

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

为什么对负数使用这种怪异的组合?简单。负数就是正数+ 1的倒数;将负数加上正数总是应该产生的0

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

这是我们将添加-1到的方法+1

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

这是我们将添加-15到的方式+15

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

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

现在,您会注意到,在将负数添加到其正数时,不是all0最右边的列将始终具有两个1s,将它们加在一起将得到2两个be的二进制表示形式10,我们将携带1到下一列,然后将0结果放置在第一列中。左侧的所有其他列只有一行带有1,因此1从上一列结转的结余将再次加到2,然后再结转...此过程重复进行,直到我们到达最左边的列,在此在1被结转无处可去,所以它溢出和丢失,我们就只剩下0一切都跨越。

该系统称为2的补码您可以在此处了解更多信息:

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


现在,以2的补码结束的崩溃过程已经结束,您将注意到,这-1是唯一二进制表示为1数字

使用~按位NOT运算符,可以反转给定数字中的所有位。0从所有位的唯一方法是,如果从头开始使用1

因此,所有这一切都是漫长的说法,~n只有0nis时才会返回-1

您可以通过以下方式使用switch语句:

switch (test.type) {

  case "itema":
  case "itemb":
  case "itemc":
  case "itemd":
    // do something
}

使用科学:您应该执行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

如果有新的事情我会更新。

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

否则,我怀疑尝试缩短它只会混淆您的代码。考虑简单地包装线使其漂亮。

if (test.type == 'itema' ||
    test.type == 'itemb' ||
    test.type == 'itemc' ||
    test.type == 'itemd') {
    do something.
}
var possibilities = {
  "itema": 1,
  "itemb": 1,
  "itemc": 1,
…};
if (test.type in possibilities) { … }

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

if( /^item[a-d]$/.test(test.type) ) { /* do something */ }

或如果项目不是那么统一,则:

if( /^(itema|itemb|itemc|itemd)$/.test(test.type) ) { /* do something */ }

很好的答案,但是您可以通过将其中之一包装在函数中来提高代码的可读性。

如果if语句很复杂,那么当您(或其他人)在几年后阅读代码时,将通过浏览找到该部分以了解正在发生的事情。具有这种业务逻辑级别的语句将使您在制定测试内容时绊倒几秒钟。像这样的代码,将允许您继续扫描。

if(CheckIfBusinessRuleIsTrue())
{
    //Do Something
}

function CheckIfBusinessRuleIsTrue() 
{
    return (the best solution from previous posts here);
}

明确命名您的函数,以便立即清楚您要测试的内容,并且使代码更易于扫描和理解。

您可以将所有答案放入Javascript集,然后仅调用.contains()集。

您仍然必须声明所有内容,但是内联调用会更短。

就像是:

var itemSet = new Set(["itema","itemb","itemc","itemd"]);
if( itemSet.contains( test.type ){}

我最喜欢的方法之一是使用underscore.js之类的库...

var isItem = _.some(['itema','itemb','itemc','itemd'], function(item) {
    return test.type === item;
});

if(isItem) {
    // One of them was true
}

http://underscorejs.org/#some

我发现的另一种方式或另一种很棒的方式是...

if ('a' in oc(['a','b','c'])) { //dosomething }

function oc(a)
{
  var o = {};
  for(var i=0;i<a.length;i++)  o[a[i]]='';
  return o;
}

当然,如您所见,这使事情更进一步,并使它们易于遵循逻辑。

http://snook.ca/archives/javascript/testing_for_a_v

使用〜&& ||之类的运算符 ((),())~~只能在稍后代码中断的情况下使用。您将不知道从哪里开始。因此,可读性大。

如果您必须将其缩短。

('a' in oc(['a','b','c'])) && statement;
('a' in oc(['a','b','c'])) && (statements,statements);
('a' in oc(['a','b','c']))?statement:elseStatement;
('a' in oc(['a','b','c']))?(statements,statements):(elseStatements,elseStatements);

如果你想做逆

('a' in oc(['a','b','c'])) || statement;

只需使用一条switch语句而不是if语句:

switch (test.type) {

  case "itema":case "itemb":case "itemc":case "itemd":
    // do your process
  case "other cases":...:
    // do other processes
  default:
    // do processes when test.type does not meet your predictions.
}

Switch 比起比较一个 if

对于很长的字符串列表,此想法将节省一些字符(并不是说我会在现实生活中推荐它,但是应该可以)。

选择一个您知道不会在test.type中出现的字符,将其用作定界符,将它们全部粘贴到一个长字符串中并搜索:

if ("/itema/itemb/itemc/itemd/".indexOf("/"+test.type+"/")>=0) {
  // doSomething
}

如果您的字符串碰巧受到进一步限制,您甚至可以省略定界符...

if ("itemaitembitemcitemd".indexOf(test.type)>=0) {
  // doSomething
}

...但是在这种情况下,您必须小心误报(例如,“ embite”在该版本中会匹配)

为了提高可读性,请为测试创建一个函数(是的,一行函数):

function isTypeDefined(test) {
    return test.type == 'itema' ||
           test.type == 'itemb' ||
           test.type == 'itemc' ||
           test.type == 'itemd';
}

然后调用它:

if (isTypeDefined(test)) {
}
...

我认为编写这种if条件时有2个目标。

  1. 简洁
  2. 可读性

因此,有时#1可能是最快的,但是以后我将采用#2以便于维护。根据情况的不同,我经常会选择Walter的答案。

首先,我有一个全局可用的函数作为现有库的一部分。

function isDefined(obj){
  return (typeof(obj) != 'undefined');
}

然后,当我实际上要运行与您的条件类似的if条件时,我将创建一个包含有效值列表的对象:

var validOptions = {
  "itema":1,
  "itemb":1,
  "itemc":1,
  "itemd":1
};
if(isDefined(validOptions[test.type])){
  //do something...
}

它不如switch / case语句那么快,并且比其他一些示例更冗长,但是我经常在代码中的其他地方重用该对象,这很方便。

我在上面制作的一个jsperf样本上搭载了此测试,并添加了一个版本来比较速度。http://jsperf.com/if-statements-test-techsin/6我注意到的最有趣的事情是,Firefox中的某些测试组合甚至比Chrome快得多。

这可以通过简单的for循环解决:

test = {};
test.type = 'itema';

for(var i=['itema','itemb','itemc']; i[0]==test.type && [
    (function() {
        // do something
        console.log('matched!');
    })()
]; i.shift());

我们使用for循环的第一部分来初始化您要匹配的参数,第二部分用于停止for循环的运行,第三部分使循环最终退出。

本文地址:http://javascript.askforanswer.com/ruhesuoduanwodetiaojianchenshu.html
文章标签: ,  
版权声明:本文为原创文章,版权归 javascript 所有,欢迎分享本文,转载请保留出处!

文件下载

老薛主机终身7折优惠码boke112

上一篇:
下一篇:

评论已关闭!