Книга: JavaScript. Подробное руководство, 6-е издание
7.11. Объекты, подобные массивам
7.11. Объекты, подобные массивам
Как мы уже видели, массивы в языке JavaScript обладают некоторыми особенностями, отсутствующими в других объектах:
• Добавление нового элемента вызывает автоматическое обновление свойства length
.
• Уменьшение значения свойства length
вызывает усечение массива.
• Массивы наследуют множество удобных методов от Array.prototype
.
• Атрибут class
массивов имеет значение «Array».
Все эти характеристики отличают массивы в языке JavaScript от других объектов. Но они не главное, что определяет массив. Часто бывает удобно организовать работу с произвольным объектом, как со своего рода массивом - через свойство length
и соответствующие неотрицательные целочисленные свойства.
Такие объекты, «подобные массивам», иногда используются для решения практических задач, и хотя с ними нельзя работать через методы массивов или ожидать специфического поведения свойства length
, все же можно организовать перебор свойств объекта теми же программными конструкциями, которые используются при работе с настоящими массивами. Оказывается, что значительное число алгоритмов для работы с массивами вполне пригодно для работы с объектами, подобными массивам. Это особенно верно, если используемые алгоритмы не изменяют массивы или хотя бы не затрагивают его свойство length
.
В следующем фрагменте создается обычный объект и к нему добавляются дополнительные свойства, которые превращают его в объект, подобный массиву, после чего производится перебор «элементов» получившегося псевдомассива:
var а = {}; // Для начала создать обычный пустой объект
// Добавить свойства, которые сделают его похожим на массив
var і = 0;
while(i < 10) {
a[i] = і * і;
і++;
}
a.length = і;
// Теперь можно обойти свойства объекта, как если бы он был настоящим массивом
var total = 0;
for(var j = 0; j < a.length; j++) total += a[j];
Объект Arguments
, который описывается в разделе 8.3.2, является объектом, подобным массиву. В клиентском языке JavaScript такие объекты возвращаются многими методами объектной модели документа (DOM), такими как метод document
. getElementsByTagName().
Следующая функция проверяет, является ли объект подобным массиву:
// Определяет, является ли о объектом, подобным массиву. Строки и функции имеют
// числовое свойство length, но они исключаются проверкой typeof.
// В клиентском JavaScript текстовые узлы D0M имеют числовое свойство length
// и, возможно, должны быть исключены дополнительной проверкой o.nodeType != 3.
function isArrayLike(o) {
if (о && // о не null, не undefined и т. д.
typeof о === "object" && //о - объект
isFinite(o.length) && // о.length - конечное число
о.length >= 0 && // о.length - положительное
о.length===Math.floor(o.length) && // о.length - целое
о.length < 4294967296) // о.length < 2~32
return true; // Значит, объект о подобен массиву
else
return false; // Иначе - нет
}
В разделе 7.12 будет показано, что строки в ECMAScript 5 ведут себя подобно массивам (и некоторые броузеры обеспечивали возможность обращения к символам в строке по индексам еще до выхода ECMAScript 5). Однако проверки на подобие массивам, такие как приведенная выше, для строк обычно возвращают false
-с ними лучше работать как со строками, чем как с массивами.
Методы массивов в языке JavaScript преднамеренно были сделаны достаточно универсальными, чтобы их можно было использовать не только с настоящими массивами, но и с объектами, подобными массивам. В ECMAScript 5 все методы массивов являются универсальными. В ECMAScript 3 универсальными также являются все методы, за исключением toString()
и toLocaleString()
. (К исключениям также относится метод concat()
: несмотря на то что его можно применять к объектам, подобным массивам, он некорректно разворачивает объекты в возвращаемый массив.) Поскольку объекты, подобные массивам, не наследуют свойства от Array.prototype
, к ним нельзя напрямую применить методы массивов. Однако их можно вызывать косвенно, с помощью метода Function.call():
var а = {"О":"а", ”2":"с”, length:3}; // Объект, подобный массиву
Array.prototype.join.call(a, "+") // => "a+b+c"
Array.prototype.slice.call(a, 0) // => ["a"."b","с"]: копия, настоящий массив
Array.prototype.map.call(a, function(x) { return x.toUpperCase();}) // => ["А","В","C"]:
Мы уже встречались с таким использованием метода саll()
в разделе 7.10, где описывался метод isArray()
. Метод саll()
объектов класса Function
детально рассматривается в разделе 8.7.3.
Методы массивов, определяемые в ECMAScript 5, были введены в Firefox 1.5. Поскольку они имели универсальную реализацию, в Firefox также были введены версии этих методов в виде функций, объявленных непосредственно в конструкторе Array
. Если использовать эти версии методов, примеры выше можно переписать так:
var а = {"О":"а", "1":"Ь", "2":"с", length;3}; // Объект, подобный массиву
Array.join(a, "+")
Array.slice(a, 0)
Array.map(a, function(x) { return x.toUpperCase(); })
Эти статические версии методов массивов чрезвычайно удобны при работе с объектами, подобными массивам, но, так как они не стандартизованы, нельзя рассчитывать, что они будут определены во всех броузерах. В своих программах вы можете использовать следующий программный код, который обеспечит доступность функций перед их использованием:
Array.join = Array.join || function(a,sep) {
return Array.prototype.join.call(a,sep);
};
Array.slice = Array.slice || function(a,from,to) {
return Array.prototype.slice.call(a,from,to);
};
Array.map = Array.map || function(a, f, thisArg) {
return Array.prototype.map.call(a, f, thisArg);
}
- 7.1. Создание массивов
- 7.2. Чтение и запись элементов массива
- 7.3. Разреженные массивы
- 7.4. Длина массива
- 7.5. Добавление и удаление элементов массива
- 7.6. Обход элементов массива
- 7.7. Многомерные массивы
- 7.8. Методы класса Array
- 7.9. Методы класса Array, определяемые стандартом ECMAScript 5
- 7.10. Тип Array
- 7.11. Объекты, подобные массивам
- 7.12. Строки как массивы
- ЧАСТЬ IV. База данных и ее объекты.
- Физические объекты
- Новые функции API для работы с Blob и массивами
- Объекты без прототипов
- Объекты базы данных
- Форматирующие объекты XSL-FO
- Практическая работа 10. Объекты на Рабочем столе
- Объекты WordArt
- Практическая работа 41. Графические объекты в документах Word
- Пользовательские объекты
- Второстепенные объекты теста
- Работа с массивами в хранимых процедурах