我正在检查一个变量,比如foo
,是否等于多个值之一。例如:
if( foo == 1 || foo == 3 || foo == 12 ) {
// ...
}
问题在于这是一个相对微不足道的任务而需要大量的代码。我想到了以下解决方案:
if( foo in {1: 1, 3: 1, 12: 1} ) {
// ...
}
但是这种方法也不完全符合我的需求,因为我必须为对象中的每个项提供冗余值。
是否有人知道一种良好的方法来检查多个值的相等性?
我正在检查一个变量,比如foo
,是否等于多个值之一。例如:
if( foo == 1 || foo == 3 || foo == 12 ) {
// ...
}
问题在于这是一个相对微不足道的任务而需要大量的代码。我想到了以下解决方案:
if( foo in {1: 1, 3: 1, 12: 1} ) {
// ...
}
但是这种方法也不完全符合我的需求,因为我必须为对象中的每个项提供冗余值。
是否有人知道一种良好的方法来检查多个值的相等性?
在ECMA2016中,你可以使用includes方法。这是我见过的最干净的方法。(被所有主要的浏览器支持)
if([1,3,12].includes(foo)) {
// ...
}
foo
在[a,b,c]
之中,或者对于字符串,如果foo
在['a','b','c']
之中,则执行下列语句。 - Hastig Zusammenstellenif([a,b,c].includes(foo))
,因为引号会将其转换为字符串。@HastigZusammenstellen - iambinodstha你可以使用一个数组和indexOf
:
if ([1,3,12].indexOf(foo) > -1)
indexOf
仅在ECMAScript第5版后才可用,因此您可能需要自己实现。 - Gumbo~
运算符代替 > -1
:if ( ~[...].indexOf(foo) ) { ... }
。 - Vahid>
运算符比使用!==
更容易阅读。 - vanowm使用提供的答案,我最终得到了以下结果:
Object.prototype.in = function() {
for(var i=0; i<arguments.length; i++)
if(arguments[i] == this) return true;
return false;
}
可以这样调用:
if(foo.in(1, 3, 12)) {
// ...
}
编辑:我最近发现了这个“技巧”,如果值是字符串并且不包含特殊字符,它会很有用。对于包含特殊字符的情况,由于需要转义,代码变得很难看,而且更容易出错。
/foo|bar|something/.test(str);
更精确地说,这将检查确切的字符串,但对于简单的相等性测试来说可能会更复杂:
/^(foo|bar|something)$/.test(str);
in
是Javascript中的一个关键字。例如,如果运行function in() {}; in()
将会导致语法错误,至少在Firefox中是这样的,我不确定为什么你的代码却没有出错。 :-) - Ben BlankObject.prototype
是一种不好的做法,因为它会对for (foo in bar)
产生不良影响。也许可以将其更改为function contains(obj) { for (var i = 1; i < arguments.length; i++) if (arguments[i] === obj) return true; return false; }
并将对象作为参数传递? - Ben BlankObject.prototype
存在严重的缺点,可能会导致许多错误。如果您真的想要扩展Object.prototype
,请始终通过Object.defineProperty
进行,而不设置描述符中的enumerable
。 - Pinke Helgax.in()
起作用的原因。在第5版之前,您必须使用计算属性名称(x["in"]()
)。 - T.J. Crowder这个很容易扩展和阅读:
switch (foo) {
case 1:
case 3:
case 12:
// ...
break
case 4:
case 5:
case 6:
// something else
break
}
const arr = [1,3,12]
if( arr.includes(foo)) { // it will return true if you `foo` is one of array values else false
// code here
}
我更喜欢上面的解决方案,而不是使用indexOf检查需要检查索引的方法。
if ( arr.indexOf( foo ) !== -1 ) { }
if(foo in L(10,20,30))
,如果您定义了L
。var L = function()
{
var obj = {};
for(var i=0; i<arguments.length; i++)
obj[arguments[i]] = null;
return obj;
};
var a = [1,2,3];
if ( a.indexOf( 1 ) !== -1 ) { }
if (!Array.prototype.indexOf)
{
Array.prototype.indexOf = function(searchElement /*, fromIndex */)
{
"use strict";
if (this === void 0 || this === null)
throw new TypeError();
var t = Object(this);
var len = t.length >>> 0;
if (len === 0)
return -1;
var n = 0;
if (arguments.length > 0)
{
n = Number(arguments[1]);
if (n !== n)
n = 0;
else if (n !== 0 && n !== (1 / 0) && n !== -(1 / 0))
n = (n > 0 || -1) * Math.floor(Math.abs(n));
}
if (n >= len)
return -1;
var k = n >= 0
? n
: Math.max(len - Math.abs(n), 0);
for (; k < len; k++)
{
if (k in t && t[k] === searchElement)
return k;
}
return -1;
};
}
var valid = [1, 3, 12];
var goodFoo = 3;
var badFoo = 55;
// Test
console.log( new Set(valid).has(goodFoo) );
console.log( new Set(valid).has(badFoo) );
如果你需要经常比较的一组较大的值,最优的做法可能是先构造一个Set
,然后使用Set#has
进行常数时间检查,而不是使用线性时间运行的Array#includes
。
const values = new Set([1, 2, 12]);
if(values.has(foo)){
// do something
}
if (_.contains([1, 3, 12], foo)) {
// ...
}
contains
在Lodash V4之前也可以使用,现在必须使用includes
if (_.includes([1, 3, 12], foo)) {
handleYellowFruit();
}
variable === value1 || value2
不起作用。对于那些想知道原因的人:||
和&&
使用短路求值;每个操作数都是真或假。x === 1 || 2
意味着(x === 1) || (2)
,它要么是true
要么是2
,因为||
的结果是第一个真值或最后一个假值操作数,而x === "a" || "b"
要么是true
要么是"b"
。由于true
、2
和"b"
都是真值,将它们放在if
条件中等同于if(true)
。只需使用[ "a", "b" ].includes(x)
。 - Sebastian Simon