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

这是我知道的唯一方法:

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

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

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


当前回答

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对象可能不是明智的做法,但有时也可以(如果您意识到这一点和权衡)。

其他回答

这里是Array.indexOf的JavaScript 1.6兼容实现:

if (!Array.indexOf) {
    Array.indexOf = [].indexOf ?
        function(arr, obj, from) {
            return arr.indexOf(obj, from);
        } :
        function(arr, obj, from) { // (for IE6)
            var l = arr.length,
                i = from ? parseInt((1 * from) + (from < 0 ? l : 0), 10) : 0;
            i = i < 0 ? 0 : i;
            for (; i < l; i++) {
                if (i in arr && arr[i] === obj) {
                    return i;
                }
            }
            return -1;
        };
}

假设您定义了这样一个数组:

const array = [1, 2, 3, 4]

下面是三种检查其中是否有3的方法。所有这些都返回true或false。

本机阵列方法(自ES2016以来)(兼容性表)

array.includes(3) // true

作为自定义数组方法(ES2016之前)

// Prefixing the method with '_' to avoid name clashes
Object.defineProperty(Array.prototype, '_includes', { value: function (v) { return this.indexOf(v) !== -1 }})
array._includes(3) // true

简单的功能

const includes = (a, v) => a.indexOf(v) !== -1
includes(array, 3) // true

正如其他人提到的,您可以使用Array.indexOf,但并非所有浏览器都可以使用。这是来自的代码https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/indexOf以使其在旧浏览器中工作相同。

indexOf是ECMA-262标准的最新添加;因此,它可能并非在所有浏览器中都存在。您可以通过插入脚本开头的以下代码,允许使用indexOf在本机不支持它的实现中。这算法完全是ECMA-262第5版中规定的算法,假设Object、TypeError、Number、Math.floor、Math.abs和Math.max具有其原始价值。

if (!Array.prototype.indexOf) {
    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {
        "use strict";
        if (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 > 1) {
            n = Number(arguments[1]);
            if (n != n) { // shortcut for verifying if it's NaN
                n = 0;
            } else if (n != 0 && n != Infinity && n != -Infinity) {
                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;
    }
}

现代浏览器具有Array#includes,这正是做到这一点的,除IE外,所有人都广泛支持它:

console.log(['joe','jane','mary']includes('jane]))//真的

您也可以使用Array#indexOf,它不那么直接,但对于过时的浏览器不需要polyfill。

console.log(['joe','jane','smary'].indexOf('jane')>=0)//真的


许多框架也提供类似的方法:

jQuery:$.inArray(value,array,[fromIndex])Undercore.js:_.inclus(数组,值)(别名为_.include和_.includes)DojoToolkit:Dojo.indexOf(array,value,[fromIndex,findLast])原型:array.indexOf(value)MooTools:array.indexOf(value)MochiKit:findValue(数组,值)MS Ajax:array.indexOf(值)Ext:Ext.Array.contains(数组,值)Lodash:_.includes(array,value,[from])(是_.包含4.0.0之前的版本)Ramda:R.includes(值,数组)

请注意,一些框架将其作为函数实现,而另一些框架将该函数添加到数组原型中。

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