, описанные выше, являются своеобразной разновидностью операции свертки массива. Однако они отличаются от
reduce
тем, что стремятся завершить обход массива как можно раньше и не всегда проверяют значения всех его элементов.
В примерах, представленных до сих пор, для простоты использовались числовые массивы, но методы
reduce
и
reduceRight
могут использоваться не только для математических вычислений. Взгляните на функцию
union
в примере 6.2. Она вычисляет «объединение» двух объектов и возвращает новый объект, имеющий свойства обоих. Эта функция принимает два объекта и возвращает другой объект, т. е. она действует как функция свертки, поэтому ее можно использовать с методом
reduce
и обобщить операцию создания объединения произвольного числа объектов:
var objects = [{х:1}, {у:2}, {z:3}];
var merged = objects.reduce(union); // => {x:1, y:2, z:3}
Напомню, что, когда два объекта имеют свойства с одинаковыми именами, функция
union
использует значение свойства второго аргумента, т.е.
reduce
и
reduceRight
могут давать разные результаты при использовании с функцией union:
var objects = [{х:1,а:1}, {у:2,а:2}, {z:3,а:3}]:
var leftunion = objects.reduce(union); // {x:1, y:2, z:3. a:3}
var rightunion = objects.reduceRight(union); // {x:1, y:2, z:3, a:1}
7.9.6. Методы indexOf и lastlndexOf
Методы
indexOf
и
lastlndexOf
отыскивают в массиве элемент с указанным значением и возвращают индекс первого найденного элемента или -1, если элемент с таким значением отсутствует. Метод
indexOf
выполняет поиск от начала массива к концу, а метод
lastlndexOf
– от конца к началу.
а = [0.1,2.1,0];
a. indexOf(1) // => 1: а[1] = 1
a.lastlndexOf(1) // => 3: а[3] = 1
a.index0f(3) // => -1: нет элемента со значением 3
В отличие от других методов, описанных в этом разделе, методы
indexOf
и
lastlndexOf
не принимают функцию в виде аргумента. В первом аргументе им передается искомое значение. Второй аргумент является необязательным: он определяет индекс массива, с которого следует начинать поиск. Если опустить этот аргумент, метод
indexOf
начнет поиск с начала массива, а метод
lastlndexOf
– с конца. Во втором аргументе допускается передавать отрицательные значения, которые интерпретируются как смещение относительно конца массива, как в методе
splice
: значение -1, например, соответствует последнему элементу массива.
Следующая функция отыскивает заданное значение в массиве и возвращает массив всех индексов, где
было найдено совпадение. Здесь демонстрируется, как можно использовать второй аргумент метода
indexOf
для поиска совпадений после первого.
// Отыскивает все вхождения значения х в массив и возвращает
// массив индексов найденных совпадений
function findall(a. х) {
var results = [], // Возвращаемый массив индексов
len = a.length, // Длина массива, где выполняется поиск
pos = 0; // Начальная позиция поиска
while(pos < len) { // Пока остались непроверенные элементы...
pos = a.indexOf(x, pos); // Искать
if (pos === -1) break; // Если ничего не найдено, поиск завершен.
results.push(pos); // Иначе - сохранить индекс в массиве
pos = pos +1; //И продолжить поиск со следующего элемента
}
return results; // Вернуть массив индексов
}
Обратите внимание, что строки также имеют методы
indexOf
и
lastlndexOf,
которые действуют подобно методам массивов.
7.10. Тип Array
На протяжении этой главы мы не раз имели возможность убедиться, что массивы являются объектами, обладающими особыми чертами поведения. Получая неизвестный объект, иногда бывает полезно проверить, является он массивом или нет. Сделать это в реализации ECMAScript 5 можно с помощью функции Array. isArray:
Array.isArray([]) // => true
Array.isArray({}) // => false
Однако до выхода стандарта ECMAScript 5 отличить массивы от других объектов было удивительно сложно. Оператор
typeof
никак не помогает в этом: для массивов он возвращает строку "object" (и для всех других объектов, кроме функций). В простых случаях можно использовать оператор
instanceof
:
[] instanceof Array // => true
({}) instanceof Array // => false
Проблема применения оператора
instanceof
состоит в том, что в веб-броузерах может быть открыто несколько окон или фреймов. Каждое окно или фрейм имеет собственное окружение JavaScript, с собственным глобальным объектом. А каждый глобальный объект имеет собственное множество функций-конструкторов. Поэтому объект из одного фрейма никогда не будет определяться как экземпляр конструктора в другом фрейме. Даже при том, что путаница между фреймами возникает довольно редко, тем не менее этого вполне достаточно, чтобы считать оператор
instanceof
ненадежным средством определения принадлежности к массивам.