ECMAScript | Абстрактная операция EnumerateObjectProperties ( O )

ECMAScript | Абстрактная операция EnumerateObjectProperties ( O )

Абстрактная операция EnumerateObjectProperties (Перечислить Свойства Объекта) принимает аргумент O (объект Object). При вызове она выполняет следующие шаги:

1. Вернуть объект Iterator (27.1.1.2), метод next которого выполняет итерацию по всем ключам со значением String перечислимых (enumerable) свойств O. 
Объект итератора никогда не доступен напрямую для кода ECMAScript. 
Механика и порядок перечисления свойств не указаны, но должны соответствовать правилам, указанным ниже.

Методы throw и return итератора имеют значение null и никогда не вызываются. Метод next итератора обрабатывает свойства объекта, чтобы определить, должен ли ключ свойства возвращаться как значение итератора. Возвращённые ключи свойств не включают ключи, которые являются символами (Symbols). Свойства целевого объекта могут быть удалены во время перечисления. Свойство, которое удаляется до того, как оно будет обработано методом next итератора, игнорируется. Если новые свойства добавляются к целевому объекту во время перечисления, не гарантируется, что новые добавленные свойства будут обработаны в активном перечислении (active enumeration). Имя свойства будет возвращено методом next итератора не более одного раза в любом перечислении.

Перечисление свойств целевого объекта включает рекурсивное перечисление свойств его прототипа, прототипа прототипа и так далее; но свойство прототипа не обрабатывается, если оно имеет то же имя, что и свойство, которое уже было обработано методом next итератора. Значения атрибутов [[Enumerable]] не учитываются при определении того, было ли уже обработано свойство объекта-прототипа. Имена перечислимых свойств объектов-прототипов должны быть получены путем вызова EnumerateObjectProperties, передавая объект-прототип в качестве аргумента. EnumerateObjectProperties должен получить собственные ключи свойств целевого объекта, вызвав его внутренний метод [[OwnPropertyKeys]]. Атрибуты свойства целевого объекта должны быть получены путём вызова его внутреннего метода [[GetOwnProperty]].

Кроме того, если ни O, ни какой-либо объект в его цепочке прототипов не является экзотическим объектом Proxy, экзотическим объектом с целочисленным индексом, экзотическим объектом пространства имен модуля или реализацией, предоставленной экзотическим объектом, то итератор должен вести себя так же, как итератор, заданный CreateForInIterator(O) до тех пор, пока не произойдет одно из следующих событий:

  • значение внутреннего слота [[Prototype]] для O или объекта в его цепочке прототипов изменяется,
  • свойство удаляется из O или объекта в его цепочке прототипов,
  • свойство добавляется к объекту в цепочке прототипов O, или
  • значение атрибута [[Enumerable]] свойства объекта O или объекта в его цепочке прототипов изменяется.
Примечание 1

Реализации ECMAScript не требуются для реализации алгоритма из 14.7.5.10.2.1 напрямую. Они могут выбрать любую реализацию, поведение которой не будет отклоняться от этого алгоритма, если не нарушено одно из ограничений в предыдущем абзаце.

Ниже приводится информативное определение функции генератора ECMAScript, которая соответствует этим правилам:

function* EnumerateObjectProperties(obj) {

    const visited = new Set();

    for (const key of Reflect.ownKeys(obj)) {

        if (typeof key === «symbol») continue;

        const desc = Reflect.getOwnPropertyDescriptor(obj, key);

        if (desc) {

            visited.add(key);

            if (desc.enumerable) yield key;

        }

    }

    const proto = Reflect.getPrototypeOf(obj);

    if (proto === null) return;

    for (const protoKey of EnumerateObjectProperties(proto)) {

        if (!visited.has(protoKey)) yield protoKey;

    }

}

 

Примечание 2

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

 

Информационные ссылки

Стандарт ECMAScript (одно-страничная версия) — Раздел «14.7.5.9 EnumerateObjectProperties ( O )» — https://tc39.es/ecma262/#sec-enumerate-object-properties

Стандарт ECMAScript (много-страничная версия) — Раздел «14.7.5.9 EnumerateObjectProperties ( O )» — https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-enumerate-object-properties