Массивоподобные объекты и работа с ними
Массивоподобным объектом является любой объект, содержащий числовые индексы и свойство length. Например объект arguments является массивоподобным объектом. Объект описанный следующим образом:
var arrayLikeObject = {
0: 'one',
1: 'two',
length: 2
};является массивоподобным. Коллекции элементов, возвращенных из методов document.querySelectorAll, document.getElementsByTagName а так же объеты, возвращаемые библиотекой jQuery являются массивоподобными объектами. Этот список того, где можно встретить массивоподобные объекты, не полон. Все примеры ниже применимы к любым массивоподобным объектам.
В консоли браузера массивоподобные объекты могут отображаться так же как и массивы. При этом массивоподобные объекты не являются массивами: у массивоподобных объектов нет методов, которые присущи массивам (indexOf, filter, forEach и другие). Поэтому при попытке вызвать метод массива у массивоподобного объекта такой код завершится исключением:
function hasTwo() {
return arguments.indexOf('two') !== -1;
}
hasTwo('one', 'two', 'three'); // ErrorКак работать с массивоподобными объектами
Цикл for
Цикл for корректно работает с массивоподобными объектами. Например функция, определяющая есть ли среди переданных ей аргументов значение 'two' может выглядеть следующим образом:
function hasTwo() {
for (var i = 0; i < arguments.length; i += 1) {
if (arguments[i] === 'two') {
return true;
}
}
return false;
}
console.log(hasTwo('uno', 'tuo', 'tre')); // false
console.log(hasTwo('one', 'two', 'three')); // trueВызов методов массивов в контексте массивоподобного объекта (одалживание метода)
Вызов методов массивов с помощью call и apply, и передачей контектом вызова ссылки на массивоподобный объект.
Например функция, определяющая есть ли среди переданных ей аргументов значение 'two' будет выглядеть следующим образом:
function hasTwo() {
return Array.prototype.indexOf.call(arguments, 'two') !== -1
}
console.log(hasTwo('uno', 'tuo', 'tre'));
console.log(hasTwo('one', 'two', 'three'));Методы массивов отрабатывают в контексте массивоподобных объектов потому что реализация методов зависит только от числовых индекстов и свойства length. Обращение к индексам и length внутри метода происходит через this.
Преобразование массивоподобного объекта в массив, и работа уже с массивом
Если при работе с массивоподобным объектом хотелось бы использовать методы массивов, можно из элементов массивоподобного объекта создать массив, и продолжать работу с массивом. Создать массив из элементов массивоподобного объекта можно с помощью цикла for. Тогда функция, определяющая есть ли среди переданных ей аргументов значение 'two' будет выглядеть следующим образом:
function hasTwo() {
var args = [];
for (var i = 0; i < arguments.length; i += 1) {
args.push(arguments[i])
}
return args.indexOf('two') !== -1
}
console.log(hasTwo('uno', 'tuo', 'tre')); // false
console.log(hasTwo('one', 'two', 'three')); // trueЛибо создание массива можно выполнить с помощью метода slice. Если метод вызывать без аргументов, он создает новый массив, в который входят все элементы массива, на котором метод был вызван. Если вызвать метод в контексте массивоподобного объекта, в результате вызова получается массив с элементами из массивоподобного объекта. Тогда функция, определяющая есть ли среди переданных ей аргументов значение 'two' будет выглядеть следующим образом:
function hasTwo() {
var args = Array.prototype.slice.call(arguments)
return args.indexOf('two') !== -1
}
console.log(hasTwo('uno', 'tuo', 'tre')); // false
console.log(hasTwo('one', 'two', 'three')); // true