Enumerabilidade e posse de propriedades

Propriedades enumeráveis são aquelas propriedades cuja flag interna [[Enumerable]] é verdadeira (true), que é o padrão para propriedades criadas via assinatura simples ou através de um inicializador (propriedades definidas através de Object.defineProperty e tipo padrão [[Enumerable]] falso (false)).Propriedades enumeráveis aparecem em for...in loops exceto se o nome da propriedade for um objeto Symbol. Posse de propriedades é determinada pelo fato da propriedade pertencer ao objeto diretamente e não a uma cadeira de protótipos. Propriedades de um objeto pode também ser recuperadas diretamente. Há um número de built-in de detecção, iteração/enumeração e recuperação de propriedades, com o gráfico mostrando que estão disponíveis.O código de exemplo a seguir demostra como obter as categorias que faltam.

Propriedade de enumerabilidade e posse - métodos internos de detecção, recuperação, e iteração
FuncionalidadePróprio objeto

Próprio objeto e sua cadeia de caracteres

Somente cadeia de protótipos
Detecção
EnumerávelNão enumerávelEnumerável e Não enumerável
propertyIsEnumerablehasOwnProperty e não propertyIsEnumerablehasOwnProperty
Não disponível sem código extraNão disponível sem código extra
Recuperação
EnumerávelNão enumerávelEnumerável e Não enumerável
Object.keysgetOwnPropertyNames filtrou-se para incluir as propriedades quando não passado propertyIsEnumerablegetOwnPropertyNames
Não disponível sem código extraNão disponível sem código extra
Iteração
EnumerávelNão enumerávelEnumerável e Não enumerável
Iterar Object.keys

itera getOwnPropertyNamesfiltrou-se para incluir as propriedades quando não passado propertyIsEnumerable

iterargetOwnPropertyNames
EnumerávelNão enumerávelEnumerável e Não enumerável
for..inNão disponível sem código extraNão disponível sem código extra
Não disponível sem código extra

Obtendo propriedades por enumerabilidade/posse

Note que não é o algoritmo mais eficiente para todos os casos, mas útil para uma demonstração rápida.

  • Detecção pode ocorrer por SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1
  • Iteração pode ocorrer por SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {}); (ou use filter(), map(), etc.)
js
var SimplePropertyRetriever = {
  getOwnEnumerables: function (obj) {
    return this._getPropertyNames(obj, true, false, this._enumerable);
    // Ou poderia usar for..in filtrado com hasOwnProperty ou apenas isto: return Object.keys(obj);
  },
  getOwnNonenumerables: function (obj) {
    return this._getPropertyNames(obj, true, false, this._notEnumerable);
  },
  getOwnEnumerablesAndNonenumerables: function (obj) {
    return this._getPropertyNames(
      obj,
      true,
      false,
      this._enumerableAndNotEnumerable,
    );
    // Ou apenas use: return Object.getOwnPropertyNames(obj);
  },
  getEnumerables: function (obj) {
    return this._getPropertyNames(obj, false, true, this._enumerable);
  },
  getNonenumerables: function (obj) {
    return this._getPropertyNames(obj, false, true, this._notEnumerable);
  },
  getEnumerablesAndNonenumerables: function (obj) {
    return this._getPropertyNames(
      obj,
      false,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  getOwnAndEnumerables: function (obj) {
    return this._getPropertyNames(obj, true, true, this._enumerable);
    // Ou poderia usar filtrado for..in
  },
  getOwnAndNonenumerables: function (obj) {
    return this._getPropertyNames(obj, true, true, this._notEnumerable);
  },
  getOwnAndEnumerablesAndNonenumerables: function (obj) {
    return this._getPropertyNames(
      obj,
      true,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  // Private static property checker callbacks
  _enumerable: function (obj, prop) {
    return obj.propertyIsEnumerable(prop);
  },
  _notEnumerable: function (obj, prop) {
    return !obj.propertyIsEnumerable(prop);
  },
  _enumerableAndNotEnumerable: function (obj, prop) {
    return true;
  },
  // Inspirado por http://stackoverflow.com/a/8024294/271577
  _getPropertyNames: function getAllPropertyNames(
    obj,
    iterateSelfBool,
    iterateBool,
    includePropCb,
  ) {
    var props = [];

    do {
      if (iterateSelfBool) {
        Object.getOwnPropertyNames(obj).forEach(function (prop) {
          if (props.indexOf(prop) === -1 && includePropCb(obj, prop)) {
            props.push(prop);
          }
        });
      }
      if (!iterateBool) {
        break;
      }
      iterateSelfBool = true;
    } while ((obj = Object.getOf(obj)));

    return props;
  },
};

Tabela de Detecção

infor..inhasOwnPropertypropertyIsEnumerablein Object.keysin Object.getOwnPropertyNamesin Object.getOwnPropertyDescriptors
Enumeráveltruetruetruetruetruetruetrue
Não enumeráveltruefalsetruefalsefalsetruetrue
Inherited Enumerabletruetruefalsefalsefalsefalsefalse
Inherited Nonenumerabletruefalsefalsefalsefalsefalsefalse
Account for Symbols keystruefalsetruetruefalsefalsetrue

Veja também