L'énumération est l'un des trois attributs d'une propriété: l'écriture, l'énumération et la configurabilité. Mes questions sont les suivantes:
pop
et push
de Array ne sont pas énumérables? Je pense que le principal avantage est de pouvoir contrôler ce qui apparaît lors de l'énumération des propriétés d'un objet, par exemple for in
ou Object.keys()
.
MDN explique bien avec Object.defineProperty
: https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/defineProperty
Donc, normalement, lorsque les gens veulent ajouter une méthode à Object
, comme un polyfill pour une méthode non prise en charge dans les anciens navigateurs, ils modifient le .prototype
. Mais cela rend la propriété énumérable et gâche ce qui est retourné dans la collection de boucles / clés ( sans utiliser .hasOwnProperty
… que tout le monde n'utilise pas).
Donc, au lieu de quelque chose comme:
Object.prototype.myMethod = function () { alert("Ahh"); };
Vous pouvez utiliser Object.defineProperty
pour dire explicitement qu'il ne soit pas énumérable:
Object.defineProperty(Object.prototype, 'myMethod', { value: function () { alert("Ahh"); }, enumerable: false });
De cette façon, par exemple lorsque vous utilisez for (var key in obj)
, "myMethod" ne sera pas un élément énuméré, et vous ne devrez pas vous soucier d'utiliser .hasOwnProperty
. Le principal problème est que certains navigateurs ne l'appuient pas bien sûr: http://kangax.github.com/es5-compat-table/ et que toutes les bibliothèques / code ne l'utilisent pas, donc vous ne pouvez toujours pas compter Sur les bibliothèques externes / code à utiliser correctement et tout le temps.
Vous pouvez accéder à une propriété non énumérable à tout moment que vous le souhaitez, il ne s'affichera plus lors de l'énumération des propriétés de l'objet – c'est le point principal.
Et je crois que toutes les propriétés "prédéfinies" des objets ne sont pas énumérées. Par cela, je ne veux dire que des propriétés natives, pas nécessairement héritées ou créées. Donc, avec votre exemple, pop
et push
ne seront pas énumérés, mais Array.prototype.indexOf
sera s'il est créé sous forme de polyfill sur un ancien navigateur qui ne prend pas en charge cette méthode … ce qui évidemment peut être évité En utilisant Object.defineProperty
comme mon exemple ci-dessus. Un autre exemple est la propriété length
, qui n'est pas énumérée.
Voici un exemple en général: http://jsfiddle.net/aHJ3g/
L'utilisation et la définition de Object.keys
est importante: "Renvoie un tableau des propriétés énumérables d'un objet donné, dans le même ordre que celui fourni par une boucle for-in
(la différence étant qu'une boucle for-in
énumère les propriétés dans le Chaîne prototype aussi). " – de MDN – https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Object/keys
Un autre avantage majeur que je le vois, c'est qu'il empêche les propriétés privées d'un objet de polluer l'espace de noms public.
Dites que vous avez créé et publié une puissante bibliothèque appelée Cosmos
. L'utilisateur déclenche l'interpréteur Node et crée une nouvelle instance en appelant le constructeur:
var Cosmos = require('Cosmos'); var cosmos = new Cosmos('my empire');
Maintenant, l'utilisateur tape simplement le cosmos
et appuyez sur Entrer pour voir l'API publique qu'il prend en charge. Lequel des deux souhaitez-vous que l'utilisateur voie?
{ name: 'my empire', grow: [Function: grow], addStar: [Function: addStar], beautify: [Function: beautify], implode: [Function: implode], destroy: [Function: destroy] }
OU
{ _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] }
Les propriétés héritées des objets intégrés (comme push, pop, toString …) ne sont pas énumérables
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