Que signifie énumérable?

151

J'ai été dirigé vers la page for..in de MDN quand il a dit, "for..in Itère sur les propriétés énumérables d'un objet."

Ensuite, je suis allé à la page Énumérabilité et propriété des propriétés où il était dit "Les propriétés énumérables sont celles qui peuvent être itérées par une boucle for..in."

Le dictionnaire définit enumerable comme dénombrable, mais je ne peux pas vraiment visualiser ce que cela signifie. Puis-je avoir un exemple de quelque chose qui est énumérable?

Patrick
la source
Comprenez-vous ce que for-infait?
D'après les réponses que j'ai obtenues pour..in permet à toutes les propriétés énumérables d'un objet d'être disponibles pour une utilisation avec l'instruction for
Patrick
6
La signification la plus simple est: si une propriété sera produite par une for inboucle ou non (pour ceux qui ne veulent pas connaître les détails ou ne s'en soucient tout simplement pas;))
Tomasz Racia

Réponses:

158

Une propriété énumérable est une propriété qui peut être incluse et visitée pendant les for..inboucles (ou une itération similaire de propriétés, comme Object.keys()).

Si une propriété n'est pas identifiée comme énumérable, la boucle ignorera qu'elle se trouve dans l'objet.

var obj = { key: 'val' };

console.log('toString' in obj); // true
console.log(typeof obj.toString); // "function"

for (var key in obj)
    console.log(key); // "key"

Une propriété est identifiée comme énumérable ou non par son propre [[Enumerable]]attribut . Vous pouvez l'afficher dans le cadre du descripteur de la propriété :

var descriptor = Object.getOwnPropertyDescriptor({ bar: 1 }, 'bar');

console.log(descriptor.enumerable); // true
console.log(descriptor.value);      // 1

console.log(descriptor);
// { value: 1, writable: true, enumerable: true, configurable: true }

Une for..inboucle parcourt ensuite les noms de propriété de l'objet.

var foo = { bar: 1, baz: 2};

for (var prop in foo)
    console.log(prop); // outputs 'bar' and 'baz'

Mais, n'évalue son instruction - console.log(prop);dans ce cas - que pour les propriétés dont l' [[Enumerable]]attribut est true.

Cette condition est en place car les objets ont beaucoup plus de propriétés , en particulier d'héritage :

console.log(Object.getOwnPropertyNames(Object.prototype));
// ["constructor", "toString", "toLocaleString", "valueOf", "hasOwnProperty", "isPrototypeOf", "propertyIsEnumerable", /* etc. */]

Chacune de ces propriétés existe toujours sur l'objet :

console.log('constructor' in foo); // true
console.log('toString' in foo);    // true
// etc.

Mais, ils sont ignorés par la for..inboucle car ils ne sont pas énumérables.

var descriptor = Object.getOwnPropertyDescriptor(Object.prototype, 'constructor');

console.log(descriptor.enumerable); // false
Jonathan Lonowski
la source
La propriété constructeur n'est donc pas énumérable car elle n'apparaît pas dans la boucle for..in. Alors que les noms des propriétés telles que bar ou baz sont énumérables car vous avez pu console.log chacun à partir de l'objet?
Patrick
5
Ce n'est pas tout à fait correct: But, they are skipped (or not counted) by the for..in loop because they are not enumerable. Les propriétés sur Object.prototypesont en fait ignorées parce qu'elles sont plus haut dans la chaîne de prototypes, pas parce qu'elles ne sont pas énumérables. Ni getOwnPropertyNames()ni keys()afficher les propriétés qui ne sont pas propres à un objet. En remarque, il est vrai que de nombreuses propriétés intégrées ne sont pas énumérables et ne s'afficheront donc pas avec keys(), mais vous devrez écrire du code supplémentaire si vous souhaitez parcourir la chaîne de prototypes.
Magnus
littéralement, énumérable signifie dénombrable
Christian Matthew
49

Si vous créez un objet via myObj = {foo: 'bar'}ou quelque chose autour, toutes les propriétés sont énumérables. La question la plus facile à poser est donc: qu'est-ce qui n'est pas énumérable? Certains objets ont des propriétés non énumérables, par exemple si vous appelez Object.getOwnPropertyNames([])(qui renvoie un tableau de toutes les propriétés, énumérables ou non, sur []), il retournera ['length'], qui inclut la propriété non énumérable d'un tableau, 'length' .

Vous pouvez créer vos propres propriétés non énumérables en appelant Object.defineProperty:

var person = { age: 18 };
Object.defineProperty(person, 'name', { value: 'Joshua', enumerable: false });

person.name; // 'Joshua'
for (prop in person) {
  console.log(prop);
}; // 'age'

Cet exemple emprunte fortement aux propriétés non énumérables en JavaScript , mais montre un objet en cours d'énumération. Les propriétés peuvent être ou non accessibles en écriture, configurables ou énumérables. John Resig en discute dans le cadre des objets et propriétés ECMAScript 5 .

Et il y a une question Stack Overflow sur la raison pour laquelle vous voudriez rendre les propriétés non énumérables .

Carpeliam
la source
Hm, les votes positifs et négatifs. S'il y a quelque chose dans cette réponse qui mérite un vote négatif, veuillez ajouter un commentaire ici.
carpeliam
1
Une autre réponse a écrit ceci: var o = {}; o ['toto'] = 0; // énumérable, normal Object.defineProperty (o, 'bar', {value: 1}); // nonenumerable, bizarre Pourquoi ajouter explicitement enumerable: false?
Patrick
5
@Patrick, je l'ai inclus ici en partie pour qu'il soit clair d'après l'exemple que c'est une option, mais en fonction de votre public, être explicite peut être une décision solide juste pour que quiconque lit votre code soit clair.
carpeliam
@carpeliam Merci pour cette explication courte et très claire, je n'ai pas pu obtenir de réponse avant d'avoir
lu la
37

C'est beaucoup plus ennuyeux que quelque chose qui devrait être visualisé.

Il y a littéralement un attribut sur toutes les propriétés appelé «énumérable». Lorsqu'il est défini sur false, lefor..in méthode ignore cette propriété, prétendant qu'elle n'existe pas.

Il y a beaucoup de propriétés sur les objets pour lesquels «énumérable» est défini sur false, comme «valueOf» et «hasOwnProperty», car il est présumé que vous ne voulez pas que le moteur JavaScript les répète.

Vous pouvez créer vos propres propriétés non énumérables à l'aide de la Object.definePropertyméthode:

  var car = {
    make: 'Honda',
    model: 'Civic',
    year: '2008',
    condition: 'bad',
    mileage: 36000
  };

  Object.defineProperty(car, 'mySecretAboutTheCar', {
    value: 'cat pee in back seat',
    enumerable: false
  });

Maintenant, le fait qu'il y ait même un secret sur la voiture est caché. Bien sûr, ils peuvent toujours accéder directement à la propriété et obtenir la réponse:

console.log(car.mySecretAboutTheCar); // prints 'cat pee in back seat'

Mais, ils devraient d'abord savoir que la propriété existe, car s'ils essaient d'y accéder via for..inou Object.keyselle restera complètement secrète:

console.log(Object.keys(car)); //prints ['make', 'model', 'year', 'condition', 'mileage']

Ils auraient dû simplement l'appeler «forInAble».

Gabriel Kunkel
la source
5
J'ai voté pour cette dernière ligne - je pense que si elle avait été appelée pour InAble, personne ne le poserait du tout. Ce qui soulève ma question: pourquoi définiriez- vous (ou pourquoi devriez-vous) une propriété pour qu'elle ne soit pas énumérable? La propriété length d'un tableau est utilisée assez souvent comme exemple de propriété non énumérable, mais pourquoi ne pas simplement la définir sur énumérable (pas la restriction JavaScript, je veux dire, pourquoi a-t-elle été définie sur non énumérable en JavaScript dans la première place)?
Chris
Pour clarifier ma question, pourquoi a-t-il été décidé que ce qui suit n'était pas une option: marque: modèle Honda: Civic secret: longueur du
Chris
Hmmm ... J'ai peut-être trouvé la réponse à ma propre question. À partir d'une recherche Google sur "Qu'entendez-vous par types de données énumérés?" Les données énumérées ont un ensemble fini de valeurs. Un type de données énuméré se compose de valeurs que vous autorisez pour ce type ou de valeurs énumérées. Pour les types énumérés à base d'entiers, chaque valeur énumérée se compose d'un nom et d'une valeur numérique sous-jacente.Ainsi, si je comprends bien, comme il existe un nombre infini de longueurs possibles, vous devrez attribuer un nombre infini de noms, un nom à chaque longueur. Est-ce exact?
Chris
Eh bien, pour répondre à votre première question, définir une propriété non énumérable sur un objet est un peu piraté, car le seul moyen de savoir ce qu'il y avait sur cet objet serait de regarder le code et en tant que base de code développe il pourrait être enterré. Donc, en général, vous ne voudriez pas l'utiliser. Concernant '.length' qui donne le nombre de caractères dans une chaîne ou des éléments dans un tableau est juste quelque chose qui est supposé que nous ne voudrions pas inclure si nous utilisions 'for ... in'. Je ne peux pas répondre pourquoi les dieux de Js l'ont fait nécessairement de cette façon. Ils ont des raisons ( ahem ) opinions au-delà de notre compréhension.
Gabriel Kunkel
... et je ne pense pas pouvoir répondre à votre deuxième question sur les types de données énumérés, même si cela ressemble à quelque chose que je pourrais mâcher pendant un certain temps si j'avais le temps. :-)
Gabriel Kunkel
9

Si vous rencontrez des difficultés pour visualiser "que signifie être énumérable?" pourquoi ne pas se demander ce que signifie être non- dénombrable ?

J'y pense un peu comme ça, une propriété non- innombrable existe mais est partiellement cachée ; ce qui signifie que non dénombrable est le plus étrange. Maintenant, vous pouvez imaginer énumérable comme ce qui reste - la propriété la plus naturelle que nous avons l'habitude de rencontrer depuis que nous avons découvert Objects . Considérer

var o = {};
o['foo'] =  0;                               // enumerable, normal
Object.defineProperty(o, 'bar', {value: 1}); // nonenumerable, weird

Maintenant dans un for..in, imaginez-le comme un pseudocode

for property in o:
    if not property enumerable continue // skip non-enumerable, "bar"
    else do /* whatever */              // act upon enumerable, "foo"

où le corps de la boucle que vous avez tapée en JavaScript est à la place de/* whatever */

Paul S.
la source
8

J'écrirai une définition de ligne de ENUMERABLE

Enumerable: Spécifie si la propriété peut être renvoyée dans une boucle for / in.

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]
Ved
la source
0

les méthodes ne sont pas énumérables; ou plutôt les méthodes intégrées ne sont pas .. tho après avoir recherché ce que signifie énumérable au script java; il fait simplement référence à un attribut de propriété .. tous les objets créés dans ecma3 sont énumérables, et ecma5 vous pouvez maintenant le définir .... c'est tout ..: D lol m'a pris un peu de temps pour trouver la réponse; mais je crois que cela en a parlé dans le livre de David Flanagan .. donc je suppose que cela signifie «caché», ou pas «caché» en ce que les méthodes ne sont pas montrées dans la boucle for in, et sont donc «cachées»

user316264
la source
0

Pensez au type de données enum, juste une structure d'objets qui correspondent à différents nombres. Déclarer quelque chose à comme énumérable, c'est déclarer qu'il correspond à un nombre spécifique, ce qui lui permet de se voir attribuer une place dans un dictionnaire qui représente les composants dénombrables d'un objet. Pour faire simple, rendre un objet énumérable équivaut à dire au compilateur: "Hé, cette propriété compte, je veux voir cela quand je vérifie les données sur cet objet."

Jeshawn Chrite
la source
0

Les méthodes intégrées dont les objets héritent ne sont pas énumérables, mais les propriétés que votre code ajoute aux objets sont énumérables sauf indication explicite

parveen mittal
la source