找出JavaScript数组是否包含值的最简洁有效的方法是什么?

这是我知道的唯一方法:

function contains(a, obj) {
    for (var i = 0; i < a.length; i++) {
        if (a[i] === obj) {
            return true;
        }
    }
    return false;
}

有没有更好、更简洁的方法来实现这一点?

这与堆栈溢出问题密切相关。在JavaScript数组中查找项目的最佳方法是什么?它解决了使用indexOf查找数组中的对象的问题。


当前回答

2019年更新:这个答案来自2008年(11岁!),与现代JS用法无关。承诺的性能改进基于当时浏览器中的基准测试。它可能与现代JS执行上下文无关。如果您需要一个简单的解决方案,请寻找其他答案。如果您需要最佳的性能,请在相关的执行环境中进行基准测试。

正如其他人所说,通过数组迭代可能是最好的方法,但事实证明,递减while循环是JavaScript中迭代最快的方法。因此,您可能需要按如下方式重写代码:

function contains(a, obj) {
    var i = a.length;
    while (i--) {
       if (a[i] === obj) {
           return true;
       }
    }
    return false;
}

当然,您还可以扩展Array原型:

Array.prototype.contains = function(obj) {
    var i = this.length;
    while (i--) {
        if (this[i] === obj) {
            return true;
        }
    }
    return false;
}

现在,您可以简单地使用以下命令:

alert([1, 2, 3].contains(2)); // => true
alert([1, 2, 3].contains('2')); // => false

其他回答

如果您只是试图检查某个值是否包含在集合中,则使用Set更合适,因为数组可以具有重复的值,而Set不能。此外,用set.has替换array.includes可以将性能从O(n2)提高到O(n)。当您必须查找同一集合的多个值时,这将非常有用。因此,如果您只是要查找一个值,那么使用set.has没有任何好处,您可以只使用array.includes。

创建了一个jsbench演示,您可以运行它来检查性能。

测试执行截图:

字面意思:

(使用Firefox v3.6,如前所述,带有for in注意事项(然而,下面的用法可能支持中的这一目的!即,枚举通过属性索引实际存在的数组元素(尤其是,数组长度属性未在for in属性列表中枚举!)。)

(拖放以下完整URI以进行即时模式浏览器测试。)

JavaScript:

  function ObjInRA(ra){var has=false; for(i in ra){has=true; break;} return has;}

  function check(ra){
      return ['There is ',ObjInRA(ra)?'an':'NO',' object in [',ra,'].'].join('')
  }
  alert([
            check([{}]), check([]), check([,2,3]),
            check(['']), '\t (a null string)', check([,,,])
        ].join('\n'));

其显示:

There is an object in [[object Object]].
There is NO object in [].
There is an object in [,2,3].
There is an object in [].
     (a null string)
There is NO object in [,,].

皱纹:如果要查找“特定”对象,请考虑:

JavaScript:警报({}!={});警报({}!=={});

因此:

JavaScript:

 obj = {prop:"value"}; 
 ra1 = [obj]; 
 ra2 = [{prop:"value"}];
 alert(ra1[0] == obj); 
 alert(ra2[0] == obj);

ra2通常被认为“包含”obj作为文本实体{prop:“value”}。

一个非常粗糙、简单、幼稚的解决方案(如代码需要增强资格):

JavaScript:

  obj={prop:"value"};   ra2=[{prop:"value"}];
  alert(
    ra2 . toSource() . indexOf( obj.toSource().match(/^.(.*).$/)[1] ) != -1 ?
      'found' :
      'missing' );

请参阅ref:在JavaScript数组中搜索对象。

Use:

Array.prototype.contains = function(x){
  var retVal = -1;

  // x is a primitive type
  if(["string","number"].indexOf(typeof x)>=0 ){ retVal = this.indexOf(x);}

  // x is a function
  else if(typeof x =="function") for(var ix in this){
    if((this[ix]+"")==(x+"")) retVal = ix;
  }

  //x is an object...
  else {
    var sx=JSON.stringify(x);
    for(var ix in this){
      if(typeof this[ix] =="object" && JSON.stringify(this[ix])==sx) retVal = ix;
    }
  }

  //Return False if -1 else number if numeric otherwise string
  return (retVal === -1)?false : ( isNaN(+retVal) ? retVal : +retVal);
}

我知道这不是最好的方法,但由于没有本机的IComparable方法来在对象之间进行交互,我想这是比较数组中两个实体所能做到的。此外,扩展Array对象可能不是明智的做法,但有时也可以(如果您意识到这一点和权衡)。

indexOf可能是,但它是“ECMA-262标准的JavaScript扩展;因此,它可能不会出现在标准的其他实现中。”

例子:

[1, 2, 3].indexOf(1) => 0
["foo", "bar", "baz"].indexOf("bar") => 1
[1, 2, 3].indexOf(4) => -1

AFAICS Microsoft没有提供某种替代方案,但如果您愿意,可以在Internet Explorer(以及其他不支持indexOf的浏览器)中的数组中添加类似的功能,正如Google快速搜索所显示的(例如,这一个)。

这绝不是最好的,但我只是在发挥创意,加入到曲目中。

不要使用此

Object.defineProperty(Array.prototype,“exists”{值:函数(元素,索引){var索引=索引||0返回索引==this.length-1:this[index]==元素?索引:this.exists(元素,++索引)}})//输出1console.log(['one','two'].exists('two'));//输出-1console.log(['one','two'].existes('tree'));console.log(['one','two','three','four'].exists('fur'));