Как проверить, содержит ли массив значение в JavaScript?

Какой самый краткий и эффективный способ выяснить, содержит ли массив JavaScript значение?

Это единственный способ, которым я знаю, чтобы сделать это:

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

Есть ли лучший и более краткий способ сделать это?

Это очень тесно связано с вопросом переполнения стека. Лучший способ найти элемент в массиве JavaScript? который обращается к поиску объектов в массиве, используя indexOf.

только что протестировано: ваш путь на самом деле самый быстрый для всех браузеров: jsperf.com/find-element-in-obj-vs-array/2 (кроме предварительного сохранения a.length в переменной) при использовании indexOf (как в $ .inArray) намного медленнее
Jörn Berkefeld 2.07.2012 11:56:14
многие ответили, что Array # indexOf - ваш лучший выбор здесь. Но если вы хотите что-то, что может быть правильно приведено к Boolean, используйте это: ~[1,2,3].indexOf(4)вернет 0, который будет оцениваться как ложный, тогда как ~[1,2,3].indexOf(3)вернет -3, который оценит как истинный.
lordvlad 2.10.2013 07:59:07
~это не то, что вы хотите использовать для преобразования в логическое значение, для этого вам нужно !. Но в этом случае вы хотите проверить равенство с -1, чтобы функция могла заканчиваться return [1,2,3].indexOf(3) === -1; ~двоичным кодом, она будет инвертировать каждый бит значения по отдельности.
mcfedr 20.06.2014 12:49:16
@Iordvlad на [1,2,3].indexOf(4)самом деле вернет -1 . Как указал @mcfedr, ~является побитовым оператором NOT , см. ES5 11.4.8. Дело в том, что, поскольку двоичное представление -1состоит только из 1, его дополнение есть 0, которое оценивается как ложное. Дополнение любого другого числа будет отличным от нуля, следовательно, истина. Итак, ~работает просто отлично и часто используется вместе с indexOf.
mknecht 14.03.2015 05:35:27
Название вводит в заблуждение. Где находится [[1,2],[3,4]].includes([3,4])?
mplungjan 2.04.2017 09:20:58
30 ОТВЕТОВ
РЕШЕНИЕ

Современные браузеры имеют Array#includes, что делает именно это и широко поддерживается всеми, кроме IE:

console.log(['joe', 'jane', 'mary'].includes('jane')); //true

Вы также можете использовать Array#indexOf, что является менее прямым, но не требует полифилов для устаревших браузеров.


Многие фреймворки также предлагают похожие методы:

Обратите внимание, что некоторые платформы реализуют это как функцию, в то время как другие добавляют функцию к прототипу массива.

4328
11.02.2020 19:13:48
MooTools также имеет Array.contains, который возвращает логическое значение, которое здесь звучит как настоящий вопрос.
Ryan Florence 8.06.2010 14:10:21
Прототип также имеет, Array.includeчто возвращает логическое значение
user102008 10.09.2010 22:54:30
Если вы используете хороший браузер, вы можете просто использоватьarray.indexOf(object) != -1
Sam Soffes 6.10.2010 16:17:24
Кроме того, не используйте в качестве условия только indexOf, поскольку первый элемент вернет 0 и будет оценен как ложный
plus- 29.02.2012 17:17:09
inArrayужасное имя для функции, которая возвращает индекс элемента, и -1если он не существует. Я ожидаю, что логическое значение будет возвращено.
Tim 22.07.2012 09:45:56

Если вы используете JavaScript 1.6 или новее (Firefox 1.5 или новее), вы можете использовать Array.indexOf . В противном случае, я думаю, вы получите что-то похожее на ваш оригинальный код.

15
25.10.2008 22:44:57

indexOf возможно, но это «расширение JavaScript к стандарту ECMA-262; как таковое оно может отсутствовать в других реализациях стандарта».

Пример:

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

AFAICS Microsoft не предлагает какой-либо альтернативы этому, но вы можете добавить аналогичные функции для массивов в Internet Explorer (и других браузерах, которые не поддерживают indexOf), если хотите, как показывает быстрый поиск в Google (например, этот ).

202
11.08.2011 23:41:11
на самом деле, есть пример реализации расширения indexOf для браузеров, которые не поддерживают его, на странице developer.mozilla.org, на которую вы ссылаетесь.
Lloyd Cotten 24.03.2009 21:24:00
на самом деле, если вы добавите indexof к прототипу Array для браузеров, которые его не поддерживают (т.е. IE7), они также попытаются перебрать эту функцию при циклическом просмотре элементов в массиве. противно.
CpILL 11.07.2012 09:13:32
это применимо для проверки на предмет? я не думаю, что это работает в случае объекта
Himesh Aadeshara 25.05.2018 04:19:13

Обновление с 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
430
7.08.2019 10:49:03
MatrixFrog 12.08.2010 23:16:50
«Проверено» - это сильное слово. Двигатели JS постоянно совершенствуются, а время выполнения, измеренное 3 года назад, ужасно устарело.
orip 20.11.2011 08:09:37
@ Дамир - я согласен. Возможно, измените пример на использование indexOf, если он доступен, просто чтобы люди, слепо копирующие этот код, получали максимальную производительность, какую только могли.
orip 20.11.2011 12:45:20
@cbmeeks да, забота определенно необходима. Вероятно, это был случай, for (o in array)который нельзя делать при циклическом прохождении массива ...
Damir Zekić 12.10.2012 13:18:45
Лучший способ сделать это - проверить, если [1, 2, 3] .indexOf (1)> -1
Devin G Rhode 28.10.2012 23:25:54

Вот совместимая с JavaScript 1.6 реализация Array.indexOf:

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;
        };
}
77
30.01.2019 10:23:54
Это выглядит великолепно, но немного запутанно: * Разве тесты в строках 1 и 3 не эквивалентны? * Не лучше ли протестировать прототип и, если необходимо, добавить функцию в Array.prototype?
Avi Flax 11.07.2010 12:31:11
Они не эквивалентны. [].indexOfэто сокращение для Array.prototype.indexOf. Мы, параноидальные защитники Javascript, избегаем расширения собственных прототипов любой ценой.
Már Örlygsson 14.07.2010 12:03:18
Разве не [].indexOfсоздается новый массив, а затем осуществляется доступ indexOf, в то время Array.prototype.indexOfкак он напрямую обращается к прототипу?
alex 8.03.2011 11:47:00
@alex да [].indexOf === Array.prototype.indexOf(попробуйте в FireBug), но наоборот [].indexOf !== Array.indexOf.
Már Örlygsson 11.03.2011 13:32:29

Расширение Arrayобъекта JavaScript - очень плохая идея, потому что вы вводите новые свойства (ваши пользовательские методы) в for-inциклы, которые могут нарушать существующие сценарии. Несколько лет назад авторам библиотеки Prototype пришлось перестроить свою библиотечную реализацию, чтобы удалить именно такие вещи.

Если вам не нужно беспокоиться о совместимости с другим JavaScript, работающим на вашей странице, воспользуйтесь этим, в противном случае я бы порекомендовал более неловкое, но более безопасное автономное функциональное решение.

48
11.08.2011 23:43:55
Я не согласен. По этой причине циклы for-in не должны использоваться для массивов. Использование циклов for-in прекратится при использовании одной из популярных библиотек js
Tomas 18.02.2011 14:51:40
Будет ли это считаться исправлением обезьяны? LOL Некоторые люди, как это.
cbmeeks 10.10.2012 20:36:26

Вот как это делает Prototype :

/**
 *  Array#indexOf(item[, offset = 0]) -> Number
 *  - item (?): A value that may or may not be in the array.
 *  - offset (Number): The number of initial items to skip before beginning the
 *      search.
 *
 *  Returns the position of the first occurrence of `item` within the array &mdash; or
 *  `-1` if `item` doesn't exist in the array.
**/
function indexOf(item, i) {
  i || (i = 0);
  var length = this.length;
  if (i < 0) i = length + i;
  for (; i < length; i++)
    if (this[i] === item) return i;
  return -1;
}

Также посмотрите здесь, как они это подключают.

4
27.08.2009 17:10:53

Подумав на секунду, если вы делаете этот вызов много раз, гораздо эффективнее использовать ассоциативный массив Map для поиска с использованием хеш-функции.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map

31
6.05.2018 18:35:49
Хотя это, очевидно, полезно для многих, было бы лучше, если бы был добавлен фрагмент кода.
Pie 'Oh' Pah 11.12.2018 19:27:31

Просто еще один вариант

// usage: if ( ['a','b','c','d'].contains('b') ) { ... }
Array.prototype.contains = function(value){
    for (var key in this)
        if (this[key] === value) return true;
    return false;
}

Будьте осторожны, поскольку перегрузка объектов массива javascript пользовательскими методами может нарушить поведение других javascript и вызвать непредвиденное поведение.

-8
30.01.2019 14:48:00
MatrixFrog 12.08.2010 23:18:09
Пожалуйста, не используйте for inцикл для итерации по массиву - for inциклы должны использоваться строго только для объектов.
Yi Jiang 20.01.2011 16:33:00
мутировать встроенный объект не очень рекомендуется ....
DAMMAK 16.10.2019 15:37:13

Если вы неоднократно проверяете наличие объекта в массиве, возможно, вам стоит

  1. Поддержание сортировки массива всегда путем вставки сортировки в ваш массив (поместите новые объекты в нужное место)
  2. Сделать обновление объектов как удаление + сортировка операции вставки и
  3. Используйте бинарный поиск в вашем contains(a, obj).
14
5.02.2011 18:02:43
Или, если возможно, полностью прекратите использование массива и вместо этого используйте объект в качестве словаря, как предложили MattMcKnight и ninjagecko.
joeytwiddle 8.07.2013 17:08:20

Буквально:

(используя Firefox v3.6, с for-inоговорками, как отмечалось ранее (ОДНАКО использование ниже может быть одобрено for-inдля этой самой цели! То есть, перечисление элементов массива, которые В РЕАЛЬНОМ СУЩЕСТВОВАНИИ существуют через индекс свойства (В частности, lengthсвойство массива НЕ перечисляется в 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: alert({}!={}); alert({}!=={});

И поэтому:

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 .

-5
23.05.2017 12:18:36

Использование:

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 может быть неуместным, но иногда это нормально (если вы знаете об этом и компромиссе).

3
7.01.2017 11:32:23
Позднее примечание: это не работает, скажем, contains([{ a: 1, b: 2 }], { b: 2, a: 1 })потому что строковые объекты поддерживают порядок свойств.
Heretic Monkey 10.10.2019 15:13:07

Допустим, вы определили массив следующим образом:

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

Ниже приведены три способа проверки наличия 3там. Все они возвращают либо trueили false.

Метод Native Array (начиная с ES2016) ( таблица совместимости )

array.includes(3) // true

Как пользовательский метод Array (до 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
111
13.11.2019 17:09:22
Он возвращает истину, если «b» находится в массиве «a» ... Я не знаю, как еще это объяснить ...
william malo 16.06.2012 00:41:36
Эту часть я не понимаю "!! ~". И я думаю, что это не будет работать в IE8, потому что IE8 не поддерживает indexOf () для объекта Array.
svlada 18.06.2012 05:29:51
«~» - это оператор, который вычитает, инвертирует и вычитает 1 из числа. indexOf возвращает -1 в случае неудачи, поэтому «~» превращает -1 в «0». с помощью "!!" витки номера в boleans (!! 0 === ложь)
william malo 19.06.2012 14:41:37
Круто, но ради простоты у вас не просто a.indexOf (b)> - 1, так как "> -1" .length === "!! ~" .length
super 16.12.2014 15:35:30
Я бы назвал отсутствие знаний об эффектах логических операторов непрофессиональным. Но я согласен с ценностью читаемого кода, я бы наверняка обернул это в четко обозначенную функцию. И это именно то, что делают большинство основных JS-фреймворков.
okdewit 19.01.2016 11:18:19

Хотя array.indexOf(x)!=-1это наиболее лаконичный способ сделать это (и поддерживается браузерами не Internet Explorer более десяти лет ...), это не O (1), а скорее O (N), что ужасно. Если ваш массив не изменится, вы можете преобразовать его в хеш-таблицу, затем выполните table[x]!==undefinedили ===undefined:

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 в две строки, это приведет к неверным результатам, если вы решите редактировать свой массив позже. У JavaScript недостаточно хуков для позвольте вам сохранить это состояние, в отличие от Python, например.)

9
7.01.2017 11:30:42
function inArray(elem,array)
{
    var len = array.length;
    for(var i = 0 ; i < len;i++)
    {
        if(array[i] == elem){return i;}
    }
    return -1;
} 

Возвращает индекс массива, если найден, или -1, если не найден

15
6.09.2014 16:22:05

Аналогичная вещь: Находит первый элемент по "поисковой лямбде":

Array.prototype.find = function(search_lambda) {
  return this[this.map(search_lambda).indexOf(true)];
};

Использование:

[1,3,4,5,8,3,5].find(function(item) { return item % 2 == 0 })
=> 4

То же самое в coffeescript:

Array.prototype.find = (search_lambda) -> @[@map(search_lambda).indexOf(true)]
2
23.11.2012 16:44:57
Это, безусловно, гораздо более гибкий, чем многие другие подходы. Если кому-то неудобно с прототипом, можно рассмотреть что-то вроде var positionIf = function (предикат, последовательность) {return sequence.map (предикат) .indexOf (true);};
dat 5.06.2013 21:28:05
Более эффективным способом реализации этого метода было бы использование цикла и прекращение применения, как search_lambdaтолько что-то найдено.
Casey Chu 10.10.2013 04:49:23

Как уже упоминали другие, вы можете использовать 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;
    }
}
3
3.08.2013 18:10:31

Я просмотрел представленные ответы и понял, что они применяются только при поиске объекта по ссылке. Простой линейный поиск со сравнением эталонного объекта.

Но допустим, у вас нет ссылки на объект, как вы найдете правильный объект в массиве? Вам придется идти линейно и глубоко сравнивать с каждым объектом. Представьте, что список слишком велик, а объекты в нем очень большие и содержат большие фрагменты текста. Производительность резко падает с количеством и размером элементов в массиве.

Вы можете упорядочить объекты и поместить их в собственную хеш-таблицу, но тогда у вас будет избыточность данных, запоминание этих ключей, потому что JavaScript сохраняет их для «for i in obj», и вам нужно только проверить, существует объект или нет, то есть У вас есть ключ.

Я думал об этом в течение некоторого времени, создавая валидатор JSON Schema, и я разработал простую оболочку для собственной хеш-таблицы, аналогичную реализации единственной хеш-таблицы, с некоторыми исключениями оптимизации, которые я оставил для работы с нативной хеш-таблицей. Требуется только тест производительности ... Все детали и код можно найти в моем блоге: http://stamat.wordpress.com/javascript-quickly-find-very-large-objects-in-a-large-array/ Я скоро опубликую результаты тестов.

Полное решение работает так:

var a = {'a':1,
 'b':{'c':[1,2,[3,45],4,5],
 'd':{'q':1, 'b':{'q':1, 'b':8},'c':4},
 'u':'lol'},
 'e':2};

 var b = {'a':1, 
 'b':{'c':[2,3,[1]],
 'd':{'q':3,'b':{'b':3}}},
 'e':2};

 var c = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.";

 var hc = new HashCache([{a:3, b:2, c:5}, {a:15, b:2, c:'foo'}]); //init

 hc.put({a:1, b:1});
 hc.put({b:1, a:1});
 hc.put(true);
 hc.put('true');
 hc.put(a);
 hc.put(c);
 hc.put(d);
 console.log(hc.exists('true'));
 console.log(hc.exists(a));
 console.log(hc.exists(c));
 console.log(hc.exists({b:1, a:1}));
 hc.remove(a);
 console.log(hc.exists(c));
2
11.09.2013 17:24:46

Использование:

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

// Usage
if(isInArray(my_array, "my_value"))
{
    //...
}
55
7.01.2017 11:29:04
x ? true : falseобычно излишним. Это здесь.
Ry-♦ 26.02.2014 16:38:53
@minitech Почему вы говорите, что это избыточно?
Matías Cánepa 3.05.2014 15:40:46
array.indexOf(search) >= 0уже логическое. Просто return array.indexOf(search) >= 0.
Ry-♦ 3.05.2014 17:38:37
@minitech хорошо, спасибо! На самом деле я не знал, что такая конструкция может быть возвращена. Пока что-то новое.
Matías Cánepa 29.07.2014 18:25:18
Буквально любая конструкция в javascript может быть возвращена
B T 15.01.2015 22:20:07

Использование:

var myArray = ['yellow', 'orange', 'red'] ;

alert(!!~myArray.indexOf('red')); //true

демонстрация

Чтобы точно знать, что tilde ~делать в этот момент, обратитесь к этому вопросу. Что делает тильда, когда она предшествует выражению? ,

8
23.05.2017 12:03:09
Это было опубликовано полтора года назад, повторять не нужно.
Shadow Wizard is Ear For You 6.10.2013 12:33:01
На самом деле, он не был опубликован. Не как ответ, а как комментарий к ответу, и даже тогда это не ясно и кратко. Спасибо за публикацию, Мина Габриэль.
T.CK 15.05.2018 14:52:54

У ECMAScript 6 есть элегантное предложение по поиску.

Метод find выполняет функцию обратного вызова один раз для каждого элемента, присутствующего в массиве, пока не найдет элемент, в котором callback возвращает истинное значение. Если такой элемент найден, find немедленно возвращает значение этого элемента. В противном случае поиск возвращает неопределенный. обратный вызов вызывается только для индексов массива, которым присвоены значения; он не вызывается для индексов, которые были удалены или которым никогда не назначались значения.

Вот документация MDN по этому вопросу.

Функциональность поиска работает следующим образом.

function isPrime(element, index, array) {
    var start = 2;
    while (start <= Math.sqrt(element)) {
        if (element % start++ < 1) return false;
    }
    return (element > 1);
}

console.log( [4, 6, 8, 12].find(isPrime) ); // Undefined, not found
console.log( [4, 5, 8, 12].find(isPrime) ); // 5

Вы можете использовать это в ECMAScript 5 и ниже, определив функцию .

if (!Array.prototype.find) {
  Object.defineProperty(Array.prototype, 'find', {
    enumerable: false,
    configurable: true,
    writable: true,
    value: function(predicate) {
      if (this == null) {
        throw new TypeError('Array.prototype.find called on null or undefined');
      }
      if (typeof predicate !== 'function') {
        throw new TypeError('predicate must be a function');
      }
      var list = Object(this);
      var length = list.length >>> 0;
      var thisArg = arguments[1];
      var value;

      for (var i = 0; i < length; i++) {
        if (i in list) {
          value = list[i];
          if (predicate.call(thisArg, value, i, list)) {
            return value;
          }
        }
      }
      return undefined;
    }
  });
}
9
7.01.2017 11:27:22
Madbreaks 16.08.2016 17:38:11

Я использую следующее:

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

var a = [ 'foo', 'bar' ];

a.contains('foo'); // true
a.contains('fox'); // false
26
15.06.2014 01:15:33

Верхние ответы предполагают примитивные типы, но если вы хотите выяснить, содержит ли массив объект с некоторой чертой, Array.prototype.some () - очень элегантное решение:

const items = [ {a: '1'}, {a: '2'}, {a: '3'} ]

items.some(item => item.a === '3')  // returns true
items.some(item => item.a === '4')  // returns false

Хорошая вещь об этом - то, что итерация прерывается, когда элемент найден, таким образом, ненужные итерационные циклы избавлены.

Кроме того, он хорошо вписывается в ifоператор, поскольку возвращает логическое значение:

if (items.some(item => item.a === '3')) {
  // do something
}

* Как отметил в комментарии jamess, на момент получения ответа, сентябрь 2018 г., Array.prototype.some()полностью поддерживается: таблица поддержки caniuse.com

122
5.09.2019 11:17:16
На сегодняшний день, сентябрь 2018 года, Array.prototype.some () полностью поддерживается: таблица поддержки
jamess 14.09.2018 22:03:31
Работа в Node> = 8.10 для AWS Node.js Lambda, так что это здорово. Очень чистое и простое решение! J
Jordan 20.09.2018 22:48:50
@jamess Это может быть хорошо поддержано, но помните, что Arrow functionsв этом примере это не так хорошо поддерживается. Для получения более подробной информации смотрите здесь: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Kamil Witkowski 24.01.2019 14:32:34
Есть ли какое-нибудь короткое замыкание? Или он повторяет весь массив, даже если он нашел значение?
Douglas Gaskell 3.10.2019 00:06:39
@DouglasGaskell прерывает итерацию, найденную (упомянуто в ответе)
Michael 14.10.2019 12:28:19

Мы используем этот фрагмент (работает с объектами, массивами, строками):

/*
 * @function
 * @name Object.prototype.inArray
 * @description Extend Object prototype within inArray function
 *
 * @param {mix}    needle       - Search-able needle
 * @param {bool}   searchInKey  - Search needle in keys?
 *
 */
Object.defineProperty(Object.prototype, 'inArray',{
    value: function(needle, searchInKey){

        var object = this;

        if( Object.prototype.toString.call(needle) === '[object Object]' || 
            Object.prototype.toString.call(needle) === '[object Array]'){
            needle = JSON.stringify(needle);
        }

        return Object.keys(object).some(function(key){

            var value = object[key];

            if( Object.prototype.toString.call(value) === '[object Object]' || 
                Object.prototype.toString.call(value) === '[object Array]'){
                value = JSON.stringify(value);
            }

            if(searchInKey){
                if(value === needle || key === needle){
                return true;
                }
            }else{
                if(value === needle){
                    return true;
                }
            }
        });
    },
    writable: true,
    configurable: true,
    enumerable: false
});

Использование:

var a = {one: "first", two: "second", foo: {three: "third"}};
a.inArray("first");          //true
a.inArray("foo");            //false
a.inArray("foo", true);      //true - search by keys
a.inArray({three: "third"}); //true

var b = ["one", "two", "three", "four", {foo: 'val'}];
b.inArray("one");         //true
b.inArray('foo');         //false
b.inArray({foo: 'val'})   //true
b.inArray("{foo: 'val'}") //false

var c = "String";
c.inArray("S");        //true
c.inArray("s");        //false
c.inArray("2", true);  //true
c.inArray("20", true); //false
15
10.09.2014 12:12:52
function contains(a, obj) {
    return a.some(function(element){return element == obj;})
}

Array.prototype.some () был добавлен к стандарту ECMA-262 в 5-м издании

23
12.09.2014 16:55:36
при использовании es6 его можно сократить какcontains = (a, obj) => a.some((element) => element === obj))
diEcho 28.05.2018 04:24:29
Даже IE9 поддерживает Array.prototype.some (), начиная с ECMAScript 5 .
Suncat2000 17.01.2019 17:45:50

ECMAScript 7 вводит Array.prototype.includes.

Это можно использовать так:

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

Он также принимает необязательный второй аргумент fromIndex:

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

В отличие от indexOf, который использует строгое сравнение равенства , includesсравнивает с использованием алгоритма равенства SameValueZero . Это означает, что вы можете определить, содержит ли массив NaN:

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

Кроме того, в отличие indexOf, includesне пропускает отсутствующие индексы:

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

В настоящее время это все еще черновик, но его можно заполнить, чтобы он работал во всех браузерах.

166
8.02.2016 16:53:32
Не поддерживается для IE и Microsfot Edge (2015) ( developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… )
Adriano Resende 5.11.2015 23:04:07
Также имеет значение таблица совместимости ES7 (похоже, что Chrome поддерживает ее сейчас)
styfle 11.03.2016 20:25:10
это применимо для проверки на предмет? я не думаю, что это работает в случае Объекта
Himesh Aadeshara 25.05.2018 04:18:49

Один лайнер:

function contains(arr, x) {
    return arr.filter(function(elem) { return elem == x }).length > 0;
}
31
7.01.2017 11:25:51
array.filter(e=>e==x).length > 0эквивалентно, array.some(e=>e==x)но someболее эффективно
Apolo 22.04.2016 09:22:25

Надеемся, более быстрый двунаправленный indexOf/ lastIndexOfальтернативный

2015

В то время как новый метод включает в себя очень хорошо, поддержка пока практически нулевая.

Давно я думал о том, как заменить медленные функции indexOf / lastIndexOf.

Эффективный путь уже найден, глядя на топовые ответы. Из них я выбрал containsфункцию @Damir Zekic, которая должна быть самой быстрой. Но в нем также говорится, что показатели взяты с 2008 года и поэтому устарели.

Я также предпочитаю whileболее for, но не по определенной причине я закончил писать эту функцию с для цикла. Это также может быть сделано с while --.

Мне было любопытно, если итерация была бы намного медленнее, если я проверяю обе стороны массива, делая это. По-видимому, нет, и поэтому эта функция примерно в два раза быстрее, чем те, которые проголосовали сверху. Очевидно, что это также быстрее, чем родной. Это в реальной среде, где вы никогда не знаете, находится ли искомое значение в начале или в конце массива.

Когда вы знаете, что вы только что выдвинули массив со значением, использование lastIndexOf остается, вероятно, лучшим решением, но если вам нужно перемещаться по большим массивам, и результат может быть везде, это может быть надежным решением для ускорения работы.

Двунаправленный indexOf / lastIndexOf

function bidirectionalIndexOf(a, b, c, d, e){
  for(c=a.length,d=c*1; c--; ){
    if(a[c]==b) return c; //or this[c]===b
    if(a[e=d-1-c]==b) return e; //or a[e=d-1-c]===b
  }
  return -1
}

//Usage
bidirectionalIndexOf(array,'value');

Тест производительности

http://jsperf.com/bidirectionalindexof

В качестве теста я создал массив с 100k записей.

Три запроса: в начале, в середине и в конце массива.

Надеюсь, вы тоже найдете это интересным и протестируете производительность.

Примечание: Как вы можете видеть, я немного изменил containsфункцию, чтобы отразить выходные данные indexOf & lastIndexOf (так, в основном, trueс indexи falseс -1). Это не должно причинить вреда.

Вариант прототипа массива

Object.defineProperty(Array.prototype,'bidirectionalIndexOf',{value:function(b,c,d,e){
  for(c=this.length,d=c*1; c--; ){
    if(this[c]==b) return c; //or this[c]===b
    if(this[e=d-1-c] == b) return e; //or this[e=d-1-c]===b
  }
  return -1
},writable:false, enumerable:false});

// Usage
array.bidirectionalIndexOf('value');

Функцию также можно легко изменить, чтобы она возвращала истину или ложь или даже объект, строку или что-то еще.

И вот whileвариант:

function bidirectionalIndexOf(a, b, c, d){
  c=a.length; d=c-1;
  while(c--){
    if(b===a[c]) return c;
    if(b===a[d-c]) return d-c;
  }
  return c
}

// Usage
bidirectionalIndexOf(array,'value');

Как это возможно?

Я думаю, что простой расчет для получения отраженного индекса в массиве настолько прост, что он в два раза быстрее, чем выполнение реальной итерации цикла.

Вот сложный пример, выполняющий три проверки за итерацию, но это возможно только при более длинных вычислениях, которые вызывают замедление кода.

http://jsperf.com/bidirectionalindexof/2

19
7.01.2017 11:42:35

Используйте lodash это некоторая функция.

Это сжато, точно и имеет большую межплатформенную поддержку.

Принятый ответ даже не соответствует требованиям.

Требования: Рекомендовать наиболее краткий и эффективный способ выяснить, содержит ли массив JavaScript объект.

Принятый ответ:

$.inArray({'b': 2}, [{'a': 1}, {'b': 2}])
> -1

Моя рекомендация:

_.some([{'a': 1}, {'b': 2}], {'b': 2})
> true

Ноты:

$ .inArray отлично работает для определения, существует ли скалярное значение в массиве скаляров ...

$.inArray(2, [1,2])
> 1

... но вопрос явно требует эффективного способа определить, содержится ли объект в массиве.

Чтобы обрабатывать как скаляры, так и объекты, вы можете сделать это:

(_.isObject(item)) ? _.some(ary, item) : (_.indexOf(ary, item) > -1)
11
21.10.2015 11:58:14

Можно использовать Set , у которого есть метод "has ()":

function contains(arr, obj) {
      var proxy = new Set(arr);
      if (proxy.has(obj))
        return true;
      else
        return false;
    }

    var arr = ['Happy', 'New', 'Year'];
    console.log(contains(arr, 'Happy'));

8
24.01.2020 12:16:00
Я думаю, что return proxy.has(obj)это намного чище, чем две строки с оператором if-else здесь
Maciej Bukowski 18.08.2016 23:30:47
function contains(arr, obj) { return new Set(arr).has(obj); }
Gordon Bean 11.03.2020 15:48:45