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
 | Funcionalidade | Próprio objeto | Próprio objeto e sua cadeia de caracteres | Somente cadeia de protótipos |
| --- | --- | --- | --- |
| Detecção | 

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `propertyIsEnumerable (en-US)` | `hasOwnProperty`
 e não
 `propertyIsEnumerable (en-US)` | `hasOwnProperty` |

 | Não disponível sem código extra | Não disponível sem código extra |
| Recuperação | 

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `Object.keys (en-US)` | `getOwnPropertyNames (en-US)`
 filtrou-se para incluir as propriedades quando não passado
 `propertyIsEnumerable (en-US)` | `getOwnPropertyNames (en-US)` |

 | Não disponível sem código extra | Não disponível sem código extra |
| Iteração | 

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| 
 Iterar
 `Object.keys (en-US)` | 
 itera
 `getOwnPropertyNames (en-US)` filtrou-se para incluir as propriedades quando não passado
 `propertyIsEnumerable (en-US)`
 | `iterargetOwnPropertyNames (en-US)` |

 | 

| Enumerável | Não enumerável | Enumerável e Não enumerável |
| --- | --- | --- |
| `for..in (en-US)` | Não disponível sem código extra | Nã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);
  },
  getPrototypeEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, false, true, this._enumerable);
  },
  getPrototypeNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, false, true, this._notEnumerable);
  },
  getPrototypeEnumerablesAndNonenumerables: function (obj) {
    return this.\_getPropertyNames(
      obj,
      false,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  getOwnAndPrototypeEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, true, this._enumerable);
    // Ou poderia usar filtrado for..in
  },
  getOwnAndPrototypeNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, true, this._notEnumerable);
  },
  getOwnAndPrototypeEnumerablesAndNonenumerables: 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,
 iteratePrototypeBool,
 includePropCb,
  ) {
    var props = [];

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

    return props;
  },
};
```

Tabela de Detecção
------------------

|  | `in` | `for..in` | `hasOwnProperty` | `propertyIsEnumerable` | `in Object.keys` | `in Object.getOwnPropertyNames` | in Object.getOwnPropertyDescriptors |
| --- | --- | --- | --- | --- | --- | --- | --- |
| Enumerável | true | true | true | true | true | true | true |
| Não enumerável | true | false | true | false | false | true | true |
| Inherited Enumerable | true | true | false | false | false | false | false |
| Inherited Nonenumerable | true | false | false | false | false | false | false |
| Account for Symbols keys | true | false | true | true | false | false | true |

Veja também
-----------

* `in` (en-US)
* `for..in` (en-US)
* `hasOwnProperty`
* `propertyIsEnumerable` (en-US)
* `getOwnPropertyNames` (en-US)
* `Object.keys` (en-US)
* `Object.getOwnPropertyDescriptors`