style img color attribute javascript prototype enumerable

javascript - img - ¿Cuáles son los beneficios de hacer que las propiedades no sean enumerables?



title html (3)

La capacidad de enumeración es uno de los tres atributos de una propiedad: capacidad de escritura, enumeración y capacidad de configuración. Mis preguntas son:

  • ¿Cuál es el beneficio de hacer las propiedades no enumerables en JavaScript? Sé que estamos ocultando la propiedad al hacer que no se puedan enumerar, pero ¿cuál es el beneficio de ocultar la propiedad?
  • ¿Podemos acceder a propiedades no enumerables? En caso afirmativo, ¿cuál es el beneficio de hacerlos no enumerables?
  • ¿Están todas las propiedades predefinidas de los objetos configuradas como no enumerables? ¿Como el caso de las propiedades pop y push de Array que no se pueden enumerar?

Creo que el principal beneficio es poder controlar lo que aparece al enumerar las propiedades de un objeto, como for in o Object.keys() .

MDN lo explica bien con Object.defineProperty : https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty

Por lo tanto, normalmente, cuando las personas desean agregar un método a Object , como un polyfill para algún método no admitido en los navegadores antiguos, modifican el .prototype . Pero eso hace que la propiedad sea enumerable y arruine lo que se devuelve en la colección de loops / keys ( sin usar .hasOwnProperty ... que no todos usan).

Entonces en lugar de algo como:

Object.prototype.myMethod = function () { alert("Ahh"); };

podría usar Object.defineProperty para decir explícitamente que no sea enumerable:

Object.defineProperty(Object.prototype, ''myMethod'', { value: function () { alert("Ahh"); }, enumerable: false });

De esta forma, por ejemplo, cuando usa for (var key in obj) , "myMethod" no será un elemento enumerado, y no tendrá que preocuparse por usar .hasOwnProperty . El principal problema con esto es que algunos navegadores no lo admiten, por supuesto: http://kangax.github.com/es5-compat-table/ y que no todas las bibliotecas / código lo usan, por lo que no siempre se puede confiar en bibliotecas externas / código para usar correctamente y todo el tiempo.

Puede acceder a una propiedad no enumerable en cualquier momento que desee, simplemente no aparecerá cuando se enumeren las propiedades del objeto, ese es el punto principal.

Y creo que todas las propiedades "predefinidas" de los objetos no son enumerables. Por eso, realmente solo me refiero a las propiedades nativas, no necesariamente heredadas o creadas. Por lo tanto, con su ejemplo, pop y push no se enumerarán más, pero Array.prototype.indexOf será si se crea como un relleno en un navegador antiguo que no admite ese método ... que, por supuesto, se puede evitar usando Object.defineProperty como mi ejemplo anterior. Otro ejemplo es la propiedad de length , que no está enumerada.

Aquí hay un ejemplo en general: http://jsfiddle.net/aHJ3g/

El uso y la definición de Object.keys es importante: "Devuelve una matriz de propiedades enumerables propias de un objeto determinado, en el mismo orden que la proporcionada por un bucle for-in (la diferencia es que un bucle for-in enumera propiedades en el cadena de prototipos también). " - de MDN - https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys


Otro beneficio importante, como yo lo veo, es que evita que las propiedades privadas de un objeto contaminen el espacio de nombres público.

Supongamos que ha creado y publicado una poderosa biblioteca llamada Cosmos . El usuario activa el intérprete de nodo y crea una nueva instancia llamando al constructor:

var Cosmos = require(''Cosmos''); var cosmos = new Cosmos(''my empire'');

Ahora el usuario simplemente escribe cosmos y presiona enter para ver qué API pública admite. ¿Cuál de los dos quieres que el usuario vea?

{ name: ''my empire'', grow: [Function: grow], addStar: [Function: addStar], beautify: [Function: beautify], implode: [Function: implode], destroy: [Function: destroy] }

O

{ _age: 25000, _size: 35000, _destroyed: false, name: ''my empire'', _numStars: 200, _init: [Function: _init], grow: [Function: grow], _grow: [Function: _grow], addStar: [Function: addStar], _checkStatus: [Function: _checkStatus], beautify: [Function: beautify], implode: [Function: implode], destroy: [Function: destroy] }


  • Al hacer que la propiedad no sea numerable, puede acceder a ella. Pero cuando aplica un bucle for in en el objeto, la propiedad no enumerable no se iterará.
  • Ver primer punto
  • Las propiedades heredadas de los objetos incorporados (como push, pop, toString ...) no son enumerables

    var o = {a:1, b:2, c:3} // a,b,c are enumerable properties o.propertyIsEnumerable("toString") // returns false, because it is a inherited property for(p in o) console.log(p); // this loop will print a,b and c but not toString or other inherited properies