Enumerabilidad y posesión de propiedades
========================================

Las propiedades enumerables son aquellas propiedades cuyo indicador enumerable interno se establece en `true`, que es el valor predeterminado para las propiedades creadas mediante una asignación simple o mediante un iniciador de propiedad (propiedades definidas mediante `Object.defineProperty` y tal valor enumerable predeterminado a `false`). Se muestran numerosas propiedades en bucles `for...in` a menos que la clave de la propiedad sea Symbol. La posesión de las propiedades está determinada por si la propiedad pertenece directamente al objeto y no a su cadena prototipo. Las propiedades de un objeto también se pueden recuperar en total. Hay varios medios incorporados para detectar, iterar/enumerar y recuperar propiedades de objetos, y el gráfico que se muestra a continuación está disponible. A continuación, se muestra un código de muestra que demuestra cómo obtener las categorías faltantes.

**Propiedad, enumerabilidad y posesión — métodos integrados de detección, recuperación e iteración.**

Funcionalidad

Detección

**Propia del Objeto**

| Enumerable | No enumerable | Enumerable y no enumerable |
| --- | --- | --- |
| `propertyIsEnumerable``hasOwnProperty` | `hasOwnProperty` — filtrado para excluir enumerables mediante `propertyIsEnumerable` | `hasOwnProperty` |

**Propia del Objeto y su cadena prototipo**

| Enumerable | No enumerable | Enumerable y no enumerable |
| --- | --- | --- |
| No disponible sin código adicional | No disponible sin código adicional | `in` |

**Solo en cadena prototipo**

No disponible sin código adicional

Recuperación

**Propia del Objeto**

| Enumerable | No enumerable | Enumerable y no enumerable |
| --- | --- | --- |
| `Object.keys``getOwnPropertyNames``getOwnPropertySymbols` | `getOwnPropertyNames`, `getOwnPropertySymbols` — filtrado para excluir enumerables usando `propertyIsEnumerable` | `getOwnPropertyNames``getOwnPropertySymbols` |

**Propia del Objeto y su cadena prototipo**

No disponible sin código adicional

**Solo en cadena prototipo**

No disponible sin código adicional

Iterable

**Propia del Objeto**

| Enumerable | No enumerable | Enumerable y no enumerable |
| --- | --- | --- |
| `Object.keys``getOwnPropertyNames``getOwnPropertySymbols` | `getOwnPropertyNames`, `getOwnPropertySymbols` — filtrado para excluir enumerables usando `propertyIsEnumerable` | `getOwnPropertyNames``getOwnPropertySymbols` |

**Propia del Objeto y su cadena prototipo**

| Enumerable | No enumerable | Enumerable y no enumerable |
| --- | --- | --- |
| `for..in`(no incluye símbolos) | No disponible sin código adicional | No disponible sin código adicional |

**Solo en cadena prototipo**

No disponible sin código adicional


Obtención de propiedades por enumerabilidad/posesión
----------------------------------------------------

Ten en cuenta que este no es el algoritmo más eficiente para todos los casos, pero es útil para una demostración rápida.

* La detección puede ocurrir por `SimplePropertyRetriever.theGetMethodYouWant(obj).indexOf(prop) > -1`
* La iteración puede ocurrir por `SimplePropertyRetriever.theGetMethodYouWant(obj).forEach(function (value, prop) {});` (o usa `filter()`, `map()`, etc.)


```js
var SimplePropertyRetriever = {
  getOwnEnumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, false, this._enumerable);
    // O podrías usar for..in filtrado con hasOwnProperty o simplemente esto: 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,
    );
    // O simplemente usa: 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);
    // O podrías usar "for..in" sin filtrar
  },
  getOwnAndPrototypeNonenumerables: function (obj) {
    return this.\_getPropertyNames(obj, true, true, this._notEnumerable);
  },
  getOwnAndPrototypeEnumerablesAndNonenumerables: function (obj) {
    return this.\_getPropertyNames(
      obj,
      true,
      true,
      this._enumerableAndNotEnumerable,
    );
  },
  // Retrollamada del supervisor de propiedad estática privada
  \_enumerable: function (obj, prop) {
    return obj.propertyIsEnumerable(prop);
  },
  \_notEnumerable: function (obj, prop) {
    return !obj.propertyIsEnumerable(prop);
  },
  \_enumerableAndNotEnumerable: function (obj, prop) {
    return true;
  },
  // Inspirado en 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;
  },
};
```

Tabla de detección
------------------

|  | `in` | `for..in` | `obj.hasOwnProperty` | `obj.propertyIsEnumerable` | `Object.keys` | `Object.getOwnPropertyNames` | `Object.getOwnPropertyDescriptors` | `Reflect.ownKeys()` |
| --- | --- | --- | --- | --- | --- | --- | --- | --- |
| Enumerable | true | true | true | true | true | true | true | true |
| No enumerable | true | false | true | false | false | true | true | true |
| Símbolos clave | true | false | true | true | false | false | true | true |
| Enumerable heredado | true | true | false | false | false | false | false | false |
| Heredado no enumerable | true | false | false | false | false | false | false | false |
| Símbolos clave heredados | true | false | false | false | false | false | false | false |

Ve también
----------

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