Статьи

Поиск с помощью Array.prototype.some


Перебор массива для поиска элемента — довольно распространенная задача.
С JavaScript
Array.prototype.forEach часто является популярным выбором. Однако в некоторых случаях
Array.prototype.some может лучше подходить для задания, если нет необходимости искать весь массив после выполнения условия.

Существует как минимум
три различных способа перебора массивов и объектов в JavaScript:
для циклов, методов массива и перечисления ключей свойств. Если итерация выполняется для выполнения операции поиска, это может привести к следующему примеру:

function findEmployee(id) {
  for (var i in employees)
    if (employees[i].id === id)
      return employees[i];
}

Без какой-либо охраны или проверки ошибок приведенный выше код не требует пояснений. Теперь, поскольку JavaScript Array имеет несколько мощных функций высшего порядка, можно, конечно, настроить вышеприведенный код так:

function findEmployee(id) {
    var employee;
    employees.forEach(function (e) {
        if (e.id === id) employee = e;
    });
    return employee;
}

Давайте рассмотрим, о чем говорится в спецификации Array.prototype.forEach(раздел 15.4.4.18 ):

callbackfn должна быть функцией, которая принимает три аргумента. forEachвызывает callbackfn один раз для каждого элемента массива в порядке возрастания.

В нашем примере задачи предположим, что идентификатор сотрудника является уникальным (в идеале, конечно, это будет ассоциативный контейнер, см. Также сообщение в блоге « Определение объектов в наборе» , но это другая история). Поиск через forEachдовольно неэффективен. Это будет продолжаться, хотя хит уже есть. Это предписано приведенной выше спецификацией, вызывая обратный вызов один раз для каждого присутствующего элемента .

Улучшение поиска может быть прекращено сразу же после выполнения условия. Обратите внимание, что условие не должно быть только одно совпадение. Есть проблемы, такие как поиск первых трех свободных мест, поиск подходящих комнат и т. Д. К счастью, есть методы Array, которые могут это сделать: everyи some. Я рассмотрел использование everyдля реализации теста на простоту (см. Предыдущее сообщение в блоге о простых числах, факториалах и рядах Фибоначчи с массивом JavaScript ), поэтому давайте взглянем на его одноуровневый элемент.

Раздел 15.4.4.17 спецификации ECMAScript 5.1 показывает, что для Array.prototype.some:

callbackfn должна быть функцией, которая принимает три аргумента и возвращает значение, которое может быть приведено к логическому значению trueили false. someвызывает callbackfn один раз для каждого элемента, присутствующего в массиве, в порядке возрастания, пока не найдет тот, который возвращает callbackfntrue .

Это именно то, что нам нужно! Перезапись предыдущего фрагмента кода дает следующую версию. Итерация не будет продолжаться, если есть совпадение.

function findEmployee(id) {
    var employee;
    employees.some(function (e) {
        if (e.id === id) {
            employee = e;
            return true;
        }
    });
    return employee;
}

Вы когда-нибудь сталкивались с ситуацией, где someможно использовать вместо forEach? Скажи нам!