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

这是我知道的唯一方法:

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

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

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


当前回答

ECMAScript 7引入了Array.prototype.includes。

它可以这样使用:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

它还接受来自Index的可选第二个参数:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

与使用严格相等比较的indexOf不同,indexOf包括使用SameValueZero相等算法的比较。这意味着您可以检测阵列是否包含NaN:

[1, 2, NaN].includes(NaN); // true

与indexOf不同,includes不会跳过缺少的索引:

new Array(5).includes(undefined); // true

它可以是多填充的,以使其在所有浏览器上都可以使用。

其他回答

很惊讶这个问题仍然没有添加最新的语法,增加了我的2美分。

假设我们有一个对象数组arrObj,我们想在其中搜索obj。

Array.prototype.indexOf->(返回索引或-1)通常用于查找数组中元素的索引。这也可用于搜索对象,但仅在传递对同一对象的引用时有效。

let obj = { name: 'Sumer', age: 36 };
let arrObj = [obj, { name: 'Kishor', age: 46 }, { name: 'Rupen', age: 26 }];


console.log(arrObj.indexOf(obj));// 0
console.log(arrObj.indexOf({ name: 'Sumer', age: 36 })); //-1

console.log([1, 3, 5, 2].indexOf(2)); //3

Array.prototype.includes->(返回true或false)

console.log(arrObj.includes(obj));  //true
console.log(arrObj.includes({ name: 'Sumer', age: 36 })); //false

console.log([1, 3, 5, 2].includes(2)); //true

Array.prototype.find->(接受回调,返回CB中返回true的第一个值/对象)。

console.log(arrObj.find(e => e.age > 40));  //{ name: 'Kishor', age: 46 }
console.log(arrObj.find(e => e.age > 40)); //{ name: 'Kishor', age: 46 }

console.log([1, 3, 5, 2].find(e => e > 2)); //3

Array.prototype.findIndex->(接受回调,返回CB中返回true的第一个值/对象的索引)。

console.log(arrObj.findIndex(e => e.age > 40));  //1
console.log(arrObj.findIndex(e => e.age > 40)); //1

console.log([1, 3, 5, 2].findIndex(e => e > 2)); //1

由于find和findIndex需要回调,所以我们可以通过创造性地设置true条件从数组中获取任何对象(即使我们没有引用)。

而array.indexOf(x)=-1是实现这一点的最简洁的方法(并且已经被非Internet Explorer浏览器支持了十多年……),它不是O(1),而是O(N),这很可怕。如果您的数组不会改变,您可以将数组转换为哈希表,然后执行表[x]==未定义或==未定义:

Array.prototype.toTable = function() {
    var t = {};
    this.forEach(function(x){t[x]=true});
    return t;
}

演示:

var toRemove = [2,4].toTable();
[1,2,3,4,5].filter(function(x){return toRemove[x]===undefined})

(不幸的是,虽然您可以创建Array.prototype.contains来“冻结”数组并将哈希表存储在this._cache中,但如果您选择稍后编辑数组,则会产生错误的结果。与Python不同,JavaScript没有足够的钩子来保持这种状态。)

ECMAScript 7引入了Array.prototype.includes。

它可以这样使用:

[1, 2, 3].includes(2); // true
[1, 2, 3].includes(4); // false

它还接受来自Index的可选第二个参数:

[1, 2, 3].includes(3, 3); // false
[1, 2, 3].includes(3, -1); // true

与使用严格相等比较的indexOf不同,indexOf包括使用SameValueZero相等算法的比较。这意味着您可以检测阵列是否包含NaN:

[1, 2, NaN].includes(NaN); // true

与indexOf不同,includes不会跳过缺少的索引:

new Array(5).includes(undefined); // true

它可以是多填充的,以使其在所有浏览器上都可以使用。

这里是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;
        };
}

字面意思:

(使用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数组中搜索对象。