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

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

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]

Пример 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, р) {
  fоr(prop in о) {                     // Для всех свойств в о
    if (!(prop in р)) delete о[prop]; // Удалить, если отсутствует в р
  }
  return о;
}
/*
*       Удаляет из объекта о свойства, присутствующие в объекте р. Возвращает о.
*/
function subtracts, р) {
  for(prop in р) {      // Для всех свойств в р
    delete о[ргор];     // Удалить из о (удаление несуществующих
                        // свойств можно выполнять без опаски)
  }
  return о;
}
/*
*       Возвращает новый объект, содержащий свойства, присутствующие хотя бы в одном
*       из объектов, о или р. Если оба объекта, о и р, имеют свойства с одним
*       и тем же именем, используется значение свойства из объекта р.
*/
function union(o,p) { return extend(extend({},о), p); }
/*
*       Возвращает новый объект, содержащий свойства, присутствующие сразу в обоих
*       объектах, о или р. Результат чем-то напоминает пересечение о и р,
*       но значения свойств объекта р отбрасываются */
function intersection(o, р) { return restrict(extend({}, о), р); }
/*
*       Возвращает массив имен собственных перечислимых свойств объекта о.
*/
function keys(o) {
  if (typeof о !== "object”) throw ТуреЕггогО; // Apr. должен быть объектом
  var result = [];         // Возвращаемый массив
  for(var prop in о) {                // Для всех перечислимых свойств
    if (о.hasOwnProperty(prop)) // Если это собственное свойство,
         result.push(prop); // добавить его в массив array.
  }
  return result;      // Вернуть массив.
}

В дополнение к циклу for/in стандарт ECMAScript 5 определяет две функции, перечисляющие имена свойств. Первая из них, Object.keys(), возвращает массив имен собственных перечислимых свойств объекта. Она действует аналогично функции keys() из примера 6.2.

Вторая функция ECMAScript 5, выполняющая перечисление свойств, - Object.getOwnPropertyNames(). Она действует подобно функции Object.keys(), но возвращает имена всех собственных свойств указанного объекта, а не только перечислимые. В реализациях ECMAScript 3 отсутствует возможность реализовать подобные функции, потому что ECMAScript 3 не предусматривает возможность получения неперечислимых свойств объекта.

Оглавление книги


Генерация: 1.317. Запросов К БД/Cache: 3 / 1
поделиться
Вверх Вниз