Чтение онлайн

ЖАНРЫ

JavaScript. Подробное руководство, 6-е издание
Шрифт:

о.х !== undefined; // true: о имеет свойство х

о.у !== undefined; // false; о не имеет свойства у

o.toString !== undefined; // true: о наследует свойство toString

Однако оператор

in
отличает ситуации, которые неотличимы при использовании представленного выше приема на основе обращения к свойству. Оператор
in
отличает отсутствие свойства от свойства, имеющего значение
undefined
. Взгляните на следующий пример:

var
о = { х: undefined } // Свойству явно присвоено значение undefined

о.х !== undefined // false: свойство имеется, но со значением undefined

о.у !== undefined // false: свойство не существует

"х" in о // true: свойство существует

"у” in о // false: свойство не существует

delete о.х; // Удалить свойство х

"х" in о // false: оно больше не существует

Обратите внимание, что в примере выше использован оператор

!==
, а не
!=
. Опера¬торы
!==
и
===
отличают значения
undefined
и
null
, хотя иногда в этом нет необходимости:

// Если о имеет свойство X, значение которого отлично от null и undefined,

// то удвоить это значение,

if (о.х != null) о.х *= 2;

// Если о имеет свойство х, значение которого не может быть преобразовано в false,

// то удвоить это значение. Если х имеет значение undefined, null, false, 0 или NaN,

// оставить его в исходном состоянии,

if (о.х) о.х *= 2;

6.5. Перечисление свойств

Вместо проверки наличия отдельных свойств иногда бывает необходимо обойти все имеющиеся свойства или получить список всех свойств объекта. Обычно для этого используется цикл

for/in
, однако стандарт ECMAScript 5 предоставляет две удобные альтернативы.

Инструкция цикла

for/in
рассматривалась в разделе 5.5.4. Она выполняет тело цикла для каждого перечислимого свойства (собственного или унаследованного) указанного объекта, присваивая имя свойства переменной цикла. Встроенные методы, наследуемые объектами, являются неперечислимыми, а свойства, добавляемые в объекты вашей программой, являются перечислимыми (если только не использовались функции, описываемые ниже, позволяющие сделать свойства неперечислимыми). Например:

var о = {х:1, у:2, z:3}; // Три собственных перечислимых свойства

о.propertyIsEnumerable("toString") // => false: неперечислимое

for(p in о) // Цикл по свойствам

console.log(p); // Выведет х, у и z, но не toString

Некоторые библиотеки добавляют новые методы (или другие свойства) в объект

Object.prototype
, чтобы они могли быть унаследованы и быть доступны всем объектам. Однако до появления стандарта ECMAScript 5 отсутствовала возможность сделать эти дополнительные методы неперечислимыми, поэтому они оказывались доступными для перечисления в циклах
for/in
.
Чтобы решить эту проблему, может потребоваться фильтровать свойства, возвращаемые циклом
for/in
. Ниже приводятся два примера реализации такой фильтрации:

fог(р in о) {

if (!о.hasOwnProperty(p)) continue; // Пропустить унаследованные свойства

}

for(p in о) {

if (typeof о[р] === "function”) continue; // Пропустить методы

}

В примере 6.2 определяются вспомогательные функции, использующие цикл for/in для управления свойствами объектов. Функция extend, в частности, часто используется в библиотеках JavaScript. [9]

9

Функция extend, представленная здесь, реализована правильно, но она не компенсирует хорошо известную проблему в Internet Explorer. Более надежная версия функции extend будет представлена в примере 8.3.

Пример 6.2. Вспомогательные функции, используемые для перечисления свойств объектов

/*

* Копирует перечислимые свойства из объекта р в объект о и возвращает о.

* Если о и р имеют свойства с одинаковыми именами, значение свойства

* в объекте о затирается значением свойства из объекта р.

* Эта функция не учитывает наличие методов доступа и не копирует атрибуты.

*/

function extend(o, р) {

fоr(ргор in р) { // Для всех свойств в р.

о[ргор] = р[prop]; // Добавить свойство в о.

}

return о;

}

/*

* Копирует перечислимые свойства из объекта р в объект о и возвращает о.

* Если о и р имеют свойства с одинаковыми именами, значение свойства

* в объекте о остается неизменным.

* Эта функция не учитывает наличие методов доступа и не копирует атрибуты.

*/

function merge(o, р) {

fоr(ргор in р) { // Для всех свойств в р.

if (о.hasOwnProperty[prop]) continue; // Кроме имеющихся в о.

о[prop] = р[prop]; // Добавить свойство в о.

}

return о;

}

/*

* Удаляет из объекта о свойства, отсутствующие в объекте р.

* Возвращает о.

*/

function restricts, р) {

Поделиться с друзьями: