确定数组是否包含值

我需要确定数组中是否存在值。

我正在使用以下功能:

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

上面的函数总是返回 false。

数组值和函数调用如下:

arrValues = ["Sam","Great", "Sample", "High"]
alert(arrValues.contains("Sam"));

答案

var contains = function(needle) {
    // Per spec, the way to identify NaN is that it is not equal to itself
    var findNaN = needle !== needle;
    var indexOf;

    if(!findNaN && typeof Array.prototype.indexOf === 'function') {
        indexOf = Array.prototype.indexOf;
    } else {
        indexOf = function(needle) {
            var i = -1, index = -1;

            for(i = 0; i < this.length; i++) {
                var item = this[i];

                if((findNaN && item !== item) || item === needle) {
                    index = i;
                    break;
                }
            }

            return index;
        };
    }

    return indexOf.call(this, needle) > -1;
};

您可以像这样使用它:

var myArray = [0,1,2],
    needle = 1,
    index = contains.call(myArray, needle); // true

CodePen 验证 / 使用

jQuery为此具有实用程序功能:

$.inArray(value, array)

返回arrayvalue索引。如果array不包含value则返回-1

另请参阅如何检查数组是否在 JavaScript 中包含对象?

通常,这就是 indexOf()方法的用途。你会说:

return arrValues.indexOf('Sam') > -1

Array.prototype.includes()

在 ES2016 中,存在Array.prototype.includes()

includes()方法确定数组是否包含某个元素,并在适当时返回truefalse

["Sam", "Great", "Sample", "High"].includes("Sam"); // true

支持

根据kangaxMDN ,支持以下平台:

  • 镀铬 47
  • 边缘 14
  • 火狐 43
  • 歌剧 34
  • 的 Safari 9
  • 节点 6

可以使用Babel (使用babel-polyfill )或core-js扩展支持。 MDN 还提供了一个polyfill

if (![].includes) {
  Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
    'use strict';
    var O = Object(this);
    var len = parseInt(O.length) || 0;
    if (len === 0) {
      return false;
    }
    var n = parseInt(arguments[1]) || 0;
    var k;
    if (n >= 0) {
      k = n;
    } else {
      k = len + n;
      if (k < 0) {k = 0;}
    }
    var currentElement;
    while (k < len) {
      currentElement = O[k];
      if (searchElement === currentElement ||
         (searchElement !== searchElement && currentElement !== currentElement)) {
        return true;
      }
      k++;
    }
    return false;
  };
}

仅仅由于跨浏览器兼容性和效率的所有问题,使用lodash这样的库几乎总是更安全。

效率,因为可以确保在任何给定时间,一个非常流行的库(例如下划线)将具有完成这样的实用程序功能的最有效方法。

_.includes([1, 2, 3], 3); // returns true

如果您担心通过包含整个库而添加到应用程序中的大量信息,请知道可以单独包含功能:

var includes = require('lodash/collections/includes');

注意:在 lodash 的旧版本中,这是_.contains()而不是_.includes()

tl; dr

function includes(k) {
  for(var i=0; i < this.length; i++){
    if( this[i] === k || ( this[i] !== this[i] && k !== k ) ){
      return true;
    }
  }
  return false;
}

function includes(k) {
  for(var i=0; i < this.length; i++){
    if( this[i] === k || ( this[i] !== this[i] && k !== k ) ){
      return true;
    }
  }
  return false;
}

function log(msg){
  $('#out').append('<div>' + msg + '</div>');  
}

var arr = [1, "2", NaN, true];
arr.includes = includes;

log('var arr = [1, "2", NaN, true];');
log('<br/>');
log('arr.includes(1): ' + arr.includes(1));
log('arr.includes(2): ' + arr.includes(2));
log('arr.includes("2"): ' + arr.includes("2"));
log('arr.includes(NaN): ' + arr.includes(NaN));
log('arr.includes(true): ' + arr.includes(true));
log('arr.includes(false): ' + arr.includes(false));
#out{
  font-family:monospace;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id=out></div>

更长的答案

我知道这个问题并不是关于是否扩展内置对象的真正问题,但是 OP 的尝试和对此答案的评论使辩论更加激烈。我在 13 年 2 月 12 日发表的评论中引用了一篇很好地概述了这场辩论的文章,但是该链接断开了,由于已经过去了太多时间,因此我无法编辑原始评论,因此在此添加了它。

如果您希望通过contains方法扩展内置的Array对象,那么最好的,最负责的方法是使用MDN 中的 polyfill 。 (另请参见 MDN 关于原型继承的文章的这一部分, 部分解释说: “扩展内置原型的唯一好理由是向后移植较新的 JavaScript 引擎的功能;例如 Array.forEach 等。”

if (!Array.prototype.includes) {
  Array.prototype.includes = function(searchElement /*, fromIndex*/ ) {
    'use strict';
    var O = Object(this);
    var len = parseInt(O.length) || 0;
    if (len === 0) {
      return false;
    }
    var n = parseInt(arguments[1]) || 0;
    var k;
    if (n >= 0) {
      k = n;
    } else {
      k = len + n;
      if (k < 0) {k = 0;}
    }
    var currentElement;
    while (k < len) {
      currentElement = O[k];
      if (searchElement === currentElement ||
         (searchElement !== searchElement && currentElement !== currentElement)) {
        return true;
      }
      k++;
    }
    return false;
  };
}

不想严格平等,还是想要选择?

function includes(k, strict) {
  strict = strict !== false; // default is true
  // strict = !!strict; // default is false
  for(var i=0; i < this.length; i++){
    if( (this[i] === k && strict) || 
        (this[i] == k && !strict) ||
        (this[i] !== this[i] && k !== k)
    ) {
      return true;
    }
  }
  return false;
}

从 ECMAScript6 开始,可以使用Set

var myArray = ['A', 'B', 'C'];
var mySet = new Set(myArray);
var hasB = mySet.has('B'); // true
var hasZ = mySet.has('Z'); // false

我的一点贡献:

function isInArray(array, search)
{
    return array.indexOf(search) >= 0;
}

//usage
if(isInArray(my_array, "my_value"))
{
    //...
}

给定 IE 的 indexOf 的实现(如失明所描述):

Array.prototype.contains = function(obj) {
    return this.indexOf(obj) > -1;
};

如果可以访问 ECMA 5,则可以使用some方法。

MDN SOME 方法链接

arrValues = ["Sam","Great", "Sample", "High"];

function namePresent(name){
  return name === this.toString();
}
// Note:
// namePresent requires .toString() method to coerce primitive value
// i.e. String {0: "S", 1: "a", 2: "m", length: 3, [[PrimitiveValue]]: "Sam"}
// into
// "Sam"

arrValues.some(namePresent, 'Sam');
=> true;

如果您有权访问 ECMA 6,则可以使用include方法。

MDN 包含方法链接

arrValues = ["Sam","Great", "Sample", "High"];

arrValues.includes('Sam');
=> true;