Javascript ассоциативные массивы цикл

Статья, в которой рассмотрим что такое ассоциативный массив, как их можно создать в JavaScript и основные принципы работы с ним.
Что такое ассоциативный массив?
Ассоциативный массив – это массив, у которого в качестве ключей используются строки.
Представить структуру данных ассоциативного массива можно как совокупность пар «ключ-значение». В ассоциативном массиве каждое значение связано с определённым ключом. Доступ к значению осуществляется по имени ключа.
Представить ассоциативный массив можно как ящичек, в котором находятся коробочки. Каждая коробочка в этом ящичке имеет имя (ключ) и содержимое (значение).
Для того чтобы найти нужную коробочку в ящичке нужно знать её имя (ключ). Зная имя (ключ) коробочки можно получить её содержимое (значение).
Создание ассоциативного массива в JavaScript
В JavaScript начиная с релиза ECMAScript 2015 (6) для создания ассоциативного массива можно использовать объект Map.
До ECMAScript 2015 не существовало типа данных, предназначенного исключительно для создания ассоциативных массивов. Их создание осуществлялось посредством объектов.
В JavaScript имеется тип данных Array. Но данный тип данных предназначен только для создания массивов, у которых в качестве ключей используются числа (индексы).
Объект Map (ассоциативный массив)
Тип данных Map предназначен для создания ассоциативных массив (пар «ключ-значение»). В качестве ключа можно использовать как примитивные, так и ссылочные типы данных. Это одно из основных отличий от ассоциативных массивов как объектов, у которых в качестве ключа можно использовать только строки.
Пример создание ассоциативного массива (экземпляра объекта Map):
// создание пустого ассоциативного массива
var arr1 = new Map();
// создание ассоциативного массива и добавление в него 3 пары “ключ-значение”
var arr = new Map([
[‘key1’, ‘value1’],
[‘key2’, ‘value2’],
[‘key3’, ‘value3’]
]);
Узнать количество элементов в массиве можно осуществить с помощью свойства size:
arr.size; // 3
Добавление элемента в массив (в экземпляр объекта Map) осуществляется с помощью метода set:
// добавить в массив одну пару “ключ-значение”
arr.set(‘key4′,’value4’);
// добавить в массив несколько пар “ключ-значение”
arr.set(‘key5′,’value5’);
arr.set(‘key6′,’value6’);
// или так
arr
.set(‘key5′,’value5’)
.set(‘key6′,’value6’);
Если в массиве есть уже такой ключ, то произойдёт установка нового значения, которое будет связано с ним:
arr.set(‘key1′,’new value’);
Получить значение по ключу выполняется с помощью метода get:
// получить значение, ассоциированное с ключом ‘key4’
arr.get(‘key4’); // ‘value4’
Проверить есть ли ключ в массиве можно посредством метода has:
// есть ли в массиве arr ключ key2
arr.has(‘key2’); // true
Удалить из ассоциативного массива (экземпляра объекта Map) элемент по имени ключа можно с помощью метода delete:
arr.delete(‘key1’); // true
Данный метод возвращает true, если данный ключ существовал в массиве, в противном случае он возвращает false.
if (arr.delete(‘key1’)) {
console.log(‘Запись с ключом “key1” удалена из массива!’);
} else {
console.log(‘Запись с ключом “key1” не найдена в массиве!’);
}
Очистить массив (удалить все элементы) можно выполнить с помощью метода clear.
arr.clear(); // очистим массив arr
arr.size; // 0 (количество элементов)
Перебор ассоциативного массива (объекта Map) обычно осуществляется с помощью цикла for…of. При этом итерацию можно организовать по ключам, значениям и записям ([key, values]).
Перебор ключей можно осуществить посредством итерируемого объекта MapIterator, возвращаемым методом keys:
for (let key of arr.keys()) {
console.log(key);
}
Для перебора значений можно воспользоваться итерируемым объектом MapIterator, возвращаемым посредством методом values:
for (let value of arr.values()) {
console.log(value);
}
Перебор записей ассоциативного массива с использованием метода entries:
for (let pair of arr.entries()) {
// pair – это массив [key, values]
console.log(pair[0]); // ключ
console.log(pair[1]); // значение
console.log(`Ключ = ${pair[0]}, значение = ${pair[1]}`);
}
Данный метод используется по умолчанию в for…of, поэтому его можно опустить:
for (let pair of arr) {
console.log(`Ключ = ${pair[0]}, значение = ${pair[1]}`);
}
Кроме этого перебрать ассоциативный массив можно с помощью метода forEach.
arr.forEach(function(value,key) {
console.log(‘key = ‘ + key +’, value = ‘ + value);
});
Преобразовать ассоциативный массив (объект Map) в JSON и обратно можно так:
let arr = new Map([
[‘question’, ‘Текст вопроса…’],
[‘answer1’, ‘Ответ 1…’],
[‘answer2’, ‘Ответ 2…’],
]);
// в JSON
jsonStr = JSON.stringify([…arr]);
// из JSON в Map
mapArr = new Map(JSON.parse(jsonStr));
Ассоциативный массив как объект
В качестве ассоциативного массива можно использовать объект.
Создать пустой ассоциативный массив (объект) можно одним из следующих способов:
// посредством литерала объекта
var arr = {};
// с использованием стандартной функции-конструктора Object
var arr = new Object();
// посредством Object.create
var arr = new Object.create(null);
Заполнить ассоциативный массив на этапе его создания можно так:
var myArray = {
“ключ1”: “значение1″
,”ключ2”: “значение2”
, … }
Добавить элемент (пару “ключ-значение”) в ассоциативный массив можно следующим образом:
// добавить в массив arr строку «текстовое значение», связанное с ключом «key1»
arr[“key1”] = “текстовое значение”
// добавить в массив число 22, связанное с ключом «key2»
arr[“key2”] = 22;
Добавление элемента в массив будет выполняться только в том случае, если данного ключа в нём нет. Если данный ключ уже имеется в ассоциативном массиве, то это выражение просто изменит значение уже существующего ключа.
В качестве значения ключа можно использовать любой тип данных в JavaScript, в том числе и объекты.
В JavaScript кроме записи с использованием квадратных скобок можно также использовать точку. Но это доступно только ключей, имена которых отвечают правилам именования переменных.
arr.key1 = “текстовое значение”
arr.key2 = 22;
Получить значение (содержимое коробочки) элемента по ключу можно с помощью следующего синтаксиса:
myArray[“key1”];
myArray[“key2”];
myArray.key1;
myArray.key2;
Получить количество ключей (длину) ассоциативного массива можно так:
var myArray = { “key1″:”value1”, “key2″:”value2”, “key3″:”value3”}
// 1 – получаем массив ключей с использованием метода keys
// 2 – используем свойство length, чтобы узнать длину массива
Object.keys(myArray).length; // 3
Удалить элемент из ассоциативного массива (объекта) выполняется с помощью оператора delete.
delete myArray[“key1”];
Проверить есть ли ключ в ассоциативном массиве можно так:
var myArray = {“key1″:”value1”, “key2″:”value2” };
// 1 способ (c использованием метода hasOwnProperty)
if (myArray.hasOwnProperty(“key1”)) {
console.log(“Ключ key1 существует!”);
} else {
console.log(“Ключ key1 не существует!”);
}
// 2 способ
if (“key1” in myArray) {
console.log(“Ключ key1 есть в массиве!”);
} else {
console.log(“Ключ key1 нет в массиве!”);
}
Перебрать элементы ассоциативного массива (свойства объекта) можно выполнить с помощью цикла for…in:
// myArray – ассоциативный массив
for(key in myArray) {
console.log(key + ” = ” + myArray[key]);
}
Преобразовать ассоциативный массив (созданный объект) в JSON и обратно можно так:
// Ассоциативный массив (объект)
var myArr = {
key1: “value1”,
key2: “value2”,
key3: “value3”
};
// в JSON
jsonStr = JSON.stringify(myArr);
// из JSON в ассоциативный массив (объект)
arr = JSON.parse(jsonStr);
//получить значение по ключу key1 (вывести в консоль)
console.log(arr.key1);
Более подробно познакомиться с форматом JSON можно в этой статье.
Источник
В этой статье мы поговорим про ассоциативные массивы. Поймём, что это такое, рассмотрим основные принципы работы с такими массивами. А также обсудим, как создать ассоциативный массив в JavaScript.
Ассоциативный массив — что это?
Под ассоциативным массивом подразумевают массив, в котором в качестве ключей применяются строки. То есть речь идёт о совокупности пар «ключ-значение». Таким образом, в ассоциативном массиве любое значение связано с конкретным ключом, а доступ к этому значению производится по имени ключа.
Мы можем представить ассоциативный массив в виде небольшого ящика, где находятся отделения. Каждое отделение имеет имя (это ключ) и содержимое (это значение). Естественно, чтобы найти нужное отделение в ящике, мы должны знать имя отделения (ключ). Зная это имя, мы сможем получить содержимое отделения (значение).
Создаём ассоциативный массив в JavaScript
Начиная с релиза ECMAScript 2015 (6), в JavaScript мы можем использовать для создания ассоциативного массива объект Map. До этого релиза в JavaScript не существовали типы данных, предназначенные лишь для создания ассоциативных массивов, поэтому создавались такие массивы с помощью объектов.
Как вы должны помнить, в JavaScript есть тип данных Array. Но этот тип данных служит лишь для создания массивов, в которых в роли ключей применяются числа (индексы).
Ассоциативный массив: объект Map
Как мы уже сказали, для создания ассоциативных массивов в JavaScript используется тип данных Map. При этом в виде ключа мы можем использовать и примитивные, и ссылочные типы данных.
Давайте посмотрим, как создаётся ассоциативный массив (экземпляр объекта Map):
var arr1 = new Map();
// создаём ассоциативный массив и добавляем три пары “ключ-значение”
var arr = new Map([
[‘key1’, ‘value1’],
[‘key2’, ‘value2’],
[‘key3’, ‘value3’]
]);
Если мы хотим узнать число элементов в массиве, пригодится свойство size:
Чтобы добавить элемент в массив (то есть в экземпляр объекта Map), используем метод set:
arr.set(‘key4′,’value4’);
// добавляем в массив несколько пар “ключ-значение”
arr.set(‘key5′,’value5’);
arr.set(‘key6′,’value6’);
// или так
arr
.set(‘key5′,’value5’)
.set(‘key6′,’value6’);
Когда в массиве такой ключ уже есть, установится новое значение, связанное с ним:
Чтобы получить значение по ключу, используем метод get:
arr.get(‘key4’); // ‘value4’
Если хотим проверить, есть ли ключ в массиве, нам пригодится метод has:
arr.has(‘key2’); // true
Чтобы удалить из ассоциативного JavaScript-массива элемент по имени ключа, применяем метод delete:
Этот метод вернёт true, если ключ существовал в массиве, иначе он вернёт false.
console.log(‘Запись с ключом “key1” удалена из массива!’);
} else {
console.log(‘Запись с ключом “key1” в массиве не найдена!’);
}
Чтобы очистить массив и удалить все элементы, подойдёт метод clear.
arr.size; // 0 (число элементов)
Перебор ассоциативного массива в JavaScript
Как правило, перебор ассоциативного массива осуществляется посредством цикла for…of. Итерацию мы можем организовать по ключам, записям и значениям ([key, values]).
Мы можем выполнить перебор ключей с помощью итерируемого объекта MapIterator, который возвращается посредством метода keys:
console.log(key);
}
Чтобы перебрать значения, воспользуйтесь итерируемым объектом MapIterator, который возвращается посредством методом values:
console.log(value);
}
Теперь посмотрим, как происходит перебор записей ассоциативного массива в JavaScript с применением метода entries:
// pair – это массив [key, values]
console.log(pair[0]); // ключ
console.log(pair[1]); // значение
console.log(`Ключ = ${pair[0]}, значение = ${pair[1]}`);
}
Этот метод по умолчанию применяется в for…of, поэтому его можно опустить:
console.log(`Ключ = ${pair[0]}, значение = ${pair[1]}`);
}
Вдобавок ко всему, перебрать ассоциативный массив в JavaScript мы можем посредством метода forEach.
console.log(‘key = ‘ + key +’, value = ‘ + value);
});
Если нужно преобразовать ассоциативный массив в JSON и назад, подойдёт следующий способ:
[‘question’, ‘Текст вопроса…’],
[‘answer1’, ‘Ответ 1…’],
[‘answer2’, ‘Ответ 2…’],
]);
// в JSON
jsonStr = JSON.stringify([…arr]);
// из JSON в Map
mapArr = new Map(JSON.parse(jsonStr));
Ассоциативный JavaScript-массив как объект
В виде ассоциативного массива мы можем использовать и объект.
Для создания пустого ассоциативного массива (объекта) нам подойдёт один из следующих вариантов:
var arr = {};
// с помощью стандартной функции-конструктора Object
var arr = new Object();
// с помощью Object.create
var arr = new Object.create(null);
Чтобы заполнить ассоциативный массив в момент его создания, поступаем следующим образом:
“ключ1”: “значение1″
,”ключ2”: “значение2”
, … }
Теперь добавим в наш ассоциативный массив элемент (пару «ключ-значение»):
arr[“key1”] = “текстовое значение”
// добавляем в массив число 22, которое связано с ключом «key2»
arr[“key2”] = 22;
Обратите внимание, что добавление элемента в JavaScript-массив выполнится лишь тогда, когда данного ключа в нём нет. Если ключ уже имеется, то выражение лишь поменяет значение уже существующего ключа.
В роли значения ключа мы можем использовать любой тип данных, включая объекты.
Стоит добавить, что в JavaScript кроме записи с квадратными скобками мы можем использовать точку. Однако это доступно лишь для ключей, имена которых соответствуют правилам именования переменных.
arr.key2 = 22;
Чтобы получить значение элемента по ключу, подойдёт следующий синтаксис:
myArray[“key2”];
myArray.key1;
myArray.key2;
Чтобы получить число ключей (длину) ассоциативного массива, поступаем следующим образом:
// 1 – получаем массив ключей посредством метода keys
// 2 – применяем свойство length, дабы узнать длину массива
Object.keys(myArray).length; // 3
Если надо удалить элемент из ассоциативного массива, применяем оператор delete.
Когда нужно проверить, существует ли ключ в нашем ассоциативном массиве:
// 1 способ (задействуем метод hasOwnProperty)
if (myArray.hasOwnProperty(“key1”)) {
console.log(“Ключ key1 есть!”);
} else {
console.log(“Ключ key1 не существует!”);
}
// 2 способ
if (“key1” in myArray) {
console.log(“Ключ key1 существует в массиве!”);
} else {
console.log(“Ключ key1 не существует в массиве!”);
}
Если нужно перебрать элементы ассоциативного массива, подойдёт цикл for…in:
for(key in myArray) {
console.log(key + ” = ” + myArray[key]);
}
А чтобы преобразовать ассоциативный JavaScript-массив в JSON и назад, поступаем так:
var myArr = {
key1: “value1”,
key2: “value2”,
key3: “value3”
};
// в JSON
jsonStr = JSON.stringify(myArr);
// из JSON в ассоциативный массив
arr = JSON.parse(jsonStr);
//получаем значение по ключу key1 (выводим в консоль)
console.log(arr.key1);
При написании статьи использовались материалы:
— «JavaScript — Ассоциативные массивы»;
— «Ассоциативный массив как объект»;
— «Настоящие ассоциативные массивы в JavaScript».
Источник
Содержание:
- I. Перебор настоящих массивов
- Метод forEach и родственные методы
- Цикл for
- Правильное использование цикла for…in
- Цикл for…of (неявное использование итератора)
- Явное использование итератора
- II. Перебор массивоподобных объектов
- Использование способов перебора настоящих массивов
- Преобразование в настоящий массив
- Замечание по объектам среды исполнения
I. Перебор настоящих массивов
На данный момент есть три способа перебора элементов настоящего массива:
- метод Array.prototype.forEach;
- классический цикл for;
- «правильно» построенный цикл for…in.
Кроме того, в скором времени, с появлением нового стандарта ECMAScript 6 (ES 6), ожидается еще два способа:
- цикл for…of (неявное использование итератора);
- явное использование итератора.
1. Метод forEach и родственные методы
Если ваш проект рассчитан на поддержку возможностей стандарта ECMAScript 5 (ES5), вы можете использовать одно из его нововведений — метод forEach.
Пример использования:
var a = [“a”, “b”, “c”];
a.forEach(function(entry) {
console.log(entry);
});
В общем случае использование forEach требует подключения библиотеки эмуляции es5-shim для браузеров, не имеющих нативной поддержки этого метода. К ним относятся IE 8 и более ранние версии, которые до сих пор кое-где еще используются.
К достоинствам forEach относится то, что здесь не нужно объявлять локальные переменные для хранения индекса и значения текущего элемента массива, поскольку они автоматически передаются в функцию обратного вызова (колбек) в качестве аргументов.
Если вас беспокоят возможные затраты на вызов колбека для каждого элемента, не волнуйтесь и прочитайте это.
forEach предназначен для перебора всех элементов массива, но кроме него ES5 предлагает еще несколько полезных методов для перебора всех или некоторых элементов плюс выполнения при этом каких-либо действий с ними:
- every — возвращает true, если для каждого элемента массива колбек возвращает значение приводимое к true.
- some — возвращает true, если хотя бы для одного элемента массива колбек возвращает значение приводимое к true.
- filter — создает новый массив, включающий те элементы исходного массива, для которых колбек возвращает true.
- map — создает новый массив, состоящий из значений возращаемых колбеком.
- reduce — сводит массив к единственному значению, применяя колбек по очереди к каждому элементу массива, начиная с первого (может быть полезен для вычисления суммы элементов массива и других итоговых функций).
- reduceRight — работает аналогично reduce, но перебирает элементы в обратном порядке.
2. Цикл for
Старый добрый for рулит:
var a = [“a”, “b”, “c”];
var index;
for (index = 0; index < a.length; ++index) {
console.log(a[index]);
}
Если длина массива неизменна в течение всего цикла, а сам цикл принадлежит критическому в плане производительности участку кода (что маловероятно), то можно использовать «более оптимальную» версию for с хранением длины массива:
var a = [“a”, “b”, “c”];
var index, len;
for (index = 0, len = a.length; index < len; ++index) {
console.log(a[index]);
}
Теоретически этот код должен выполняться чуть быстрее, чем предыдущий.
Если порядок перебора элементов не важен, то можно пойти еще дальше в плане оптимизации и избавиться от переменной для хранения длины массива, изменив порядок перебора на обратный:
var a = [“a”, “b”, “c”];
var index;
for (index = a.length – 1; index >= 0; –index) {
console.log(a[index]);
}
Тем не менее, в современных движках JavaScript подобные игры с оптимизацией обычно ничего не значат.
3. Правильное использование цикла for…in
Если вам посоветуют использовать цикл for…in, помните, что перебор массивов — не то, для чего он предназначен. Вопреки распространенному заблуждению цикл for…in перебирает не индексы массива, а перечислимые свойства объекта.
Тем не менее, в некоторых случаях, таких как перебор разреженных массивов, for…in может оказаться полезным, если только соблюдать при этом меры предосторожности, как показано в примере ниже:
// a – разреженный массив
var a = [];
a[0] = “a”;
a[10] = “b”;
a[10000] = “c”;
for (var key in a) {
if (a.hasOwnProperty(key) &&
/^0$|^[1-9]d*$/.test(key) &&
key <= 4294967294) {
console.log(a[key]);
}
}
В данном примере на каждой итерации цикла выполняется две проверки:
- то, что массив имеет собственное свойство с именем key (не наследованное из его прототипа).
- то, что key — строка, содержащая десятичную запись целого числа, значение которого меньше 4294967294. Откуда берется последнее число? Из определения индекса массива в ES5, из которого следует, что наибольший индекс, который может иметь элемент в массиве: (2^32 – 2) = 4294967294.
Конечно, такие проверки отнимут лишнее время при выполнении цикла. Но в случае разреженного массива этот способ более эффективен, чем цикл for, поскольку в этом случае перебираются только те элементы, которые явно определены в массиве. Так, в примере выше будет выполнено всего 3 итерации (для индексов 0, 10 и 10000) — против 10001 в цикле for.
Чтобы не писать такой громоздкий код проверок каждый раз, когда требуется перебор массива, можно оформить его в виде отдельной функции:
function arrayHasOwnIndex(array, key) {
return array.hasOwnProperty(key) && /^0$|^[1-9]d*$/.test(key) && key <= 4294967294;
}
Тогда тело цикла из примера значительно сократится:
for (key in a) {
if (arrayHasOwnIndex(a, key)) {
console.log(a[key]);
}
}
Рассмотренный выше код проверок является универсальным, подходящим для всех случаев. Но вместо него можно использовать более короткую версию, хотя формально и не совсем правильную, но, тем не менее, подходящую для большинства случаев:
for (key in a) {
if (a.hasOwnProperty(key) && String(parseInt(key, 10)) === key) {
console.log(a[key]);
}
}
4. Цикл for…of (неявное использование итератора)
ES6, пока все еще пребывающий в статусе черновика, должен ввести в JavaScript итераторы.
Итератор — это реализуемый объектом протокол, который определяет стандартный способ получения последовательности значений (конечной или бесконечной).
Итератор — это объект, в котором определен метод next() — функция без аргументов, возвращающая объект с двумя свойствами:
- done (boolean) — принимает значение true, если итератор достиг конца итерируемой последовательности. В противном случае имеет значение false.
- value — определяет значение, возвращаемое итератором. Может быть не определено (отсутствовать), если свойство done имеет значение true.
Многие встроенные объекты, в т.ч. настоящие массивы, имеют итераторы по умолчанию. Простейший способ применения итератора в настоящих массивах — использовать новую конструкцию for…of.
Пример использования for…of:
var val;
var a = [“a”, “b”, “c”];
for (val of a) {
console.log(val);
}
В приведенном примере цикл for…of неявно вызывает итератор объекта Array для получения каждого значения массива.
5. Явное использование итератора
Итераторы можно также использовать и явно, правда, в этом случае код становится значительно сложнее, по сравнению с циклом for…of. Выглядит это примерно так:
var a = [“a”, “b”, “c”];
var it = a.entries();
var entry;
while (!(entry = it.next()).done) {
console.log(entry.value[1]);
}
В данном примере метод Array.prototype.entries возвращает итератор, который используется для вывода значений массива. На каждой итерации entry.value содержит массив вида [ключ, значение].
II. Перебор массивоподобных объектов
Кроме настоящих массивов, в JavaScript встречаются также массивоподобные объекты. С настоящими массивами их роднит то, что они имеют свойство length и свойства с именами в виде чисел, соответствующие элементам массива. В качестве примеров можно назвать DOM коллекции NodeList и псевдомассив arguments, доступный внутри любой функции/метода.
1. Использование способов перебора настоящих массивов
Как минимум большинство, если не все, способы перебора настоящих массивов могут быть применены для перебора массивоподобных объектов.
Конструкции for и for…in могут быть применены к массивоподобным объектам точно тем же путем, что и к настоящим массивам.
forEach и другие методы Array.prototype также применимы к массивоподобным объектам. Для этого нужно использовать вызов Function.call или Function.apply.
Например, если вы хотите применить forEach к свойству childNodes объекта Node, то это делается так:
Array.prototype.forEach.call(node.childNodes, function(child) {
// делаем что-нибудь с объектом child
});
Для удобства повторного использования этого приема, можно объявить ссылку на метод Array.prototype.forEach в отдельной переменной и использовать ее как сокращение:
// (Предполагается, что весь код ниже находится в одной области видимости)
var forEach = Array.prototype.forEach;
// …
forEach.call(node.childNodes, function(child) {
// делаем что-нибудь с объектом child
});
Если в массивоподобном объекте имеется итератор, то его можно использовать явно или неявно для перебора объекта таким же способом, как и для настоящих массивов.
2. Преобразование в настоящий массив
Есть также еще один, очень простой, способ перебора массивоподобного объекта: преобразовать его в настоящий массив и использовать любой из рассмотренных выше способов перебора настоящих массивов. Для преобразования можно использовать универсальный метод Array.prototype.slice, который может быть применен к любому массивоподобному объекту. Делается это очень просто, как показано в примере ниже:
var trueArray = Array.prototype.slice.call(arrayLikeObject, 0);
Например, если вы хотите преобразовать коллекцию NodeList в настоящий массив, вам нужен примерно такой код:
var divs = Array.prototype.slice.call(document.querySelectorAll(“div”), 0);
Update: Как было отмечено в комментариях rock и torbasow, в ES6 вместо Array.prototype.slice можно использовать более наглядный метод Array.from.
3. Замечание по объектам среды исполнения
Если вы применяете методы Array.prototype к объектам среды исполнения (таких как DOM коллекции), то вы должны иметь в виду, что правильная работа этих методов не гарантирована во всех средах исполнения (в т.ч. в браузерах). Это зависит от поведения конкретного объекта в конкретной среде исполнения, если точнее, от того, как в этом объекте реализована абстрактная операция HasProperty. Проблема в том, что сам стандарт ES5 допускает возможность неправильного поведения объекта по отношению к этой операции (см. §8.6.2).
Поэтому важно тестировать работу методов Array.prototype в каждой среде исполнения (браузере), в которой планируется использование вашего приложения.
Источник