O que significa enumerável?

151

Fui direcionado para as MDN's da página for..in quando dizia "for..in" itera sobre as propriedades enumeráveis ​​de um objeto ".

Depois fui para a página Enumerabilidade e propriedade das propriedades, onde dizia "Propriedades enumeráveis ​​são aquelas que podem ser iteradas por um loop for..in".

O dicionário define enumerável como contável, mas não consigo realmente visualizar o que isso significa. Eu poderia obter um exemplo de algo sendo enumerável?

Patrick
fonte
Você entende o que for-infaz?
A partir das respostas que eu tenho que for..in permite que todas as propriedades enumeráveis de um objeto que esteja disponível para uso com a instrução for
Patrick
6
O significado mais simples é: se uma propriedade será produzido por um for inloop ou não (para aqueles que não querem saber os detalhes ou simplesmente não se importam;))
Tomasz Racia

Respostas:

158

Uma propriedade enumerável é aquela que pode ser incluída e visitada durante for..inloops (ou uma iteração semelhante de propriedades, como Object.keys()).

Se uma propriedade não for identificada como enumerável, o loop ignorará que está dentro do objeto.

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"

Uma propriedade é identificada como enumerável ou não por seu próprio [[Enumerable]]atributo . Você pode visualizar isso como parte do descritor da propriedade :

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 }

Um for..inloop itera pelos nomes das propriedades do objeto.

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

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

Mas, apenas avalia sua declaração - console.log(prop);nesse caso - para aquelas propriedades cujo [[Enumerable]]atributo é true.

Essa condição está em vigor porque os objetos têm muito mais propriedades , especialmente de herança :

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

Cada uma dessas propriedades ainda existe no objeto :

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

Mas, eles são ignorados pelo for..inloop porque não são enumeráveis.

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

console.log(descriptor.enumerable); // false
Jonathan Lonowski
fonte
Portanto, a propriedade construtora não é enumerável porque não aparece no loop for..in. Enquanto os nomes das propriedades, como bar ou baz, são enumeráveis ​​porque você conseguiu console.log cada um do objeto?
287 Patrick
5
Isso não é inteiramente correto: But, they are skipped (or not counted) by the for..in loop because they are not enumerable. As propriedades on Object.prototypesão de fato ignoradas porque estão mais acima na cadeia de protótipos, não porque não são enumeráveis. Nem mostre getOwnPropertyNames()nem keys()propriedades que não sejam de um objeto. Como uma observação lateral, é verdade que muitas das propriedades internas não são enumeráveis ​​e, portanto, não serão exibidas keys(), mas você precisará escrever um código extra se desejar percorrer a cadeia de protótipos.
Magnus
literalmente, enumerável significa contável
Christian Matthew
49

Se você criar um objeto via myObj = {foo: 'bar'}ou algo a seguir, todas as propriedades serão enumeráveis. Portanto, a pergunta mais fácil a ser feita é: o que não é enumerável? Certos objetos têm algumas propriedades não enumeráveis, por exemplo, se você chamar Object.getOwnPropertyNames([])(que retorna uma matriz de todas as propriedades, enumeráveis ​​ou não, em []), ele retornará ['length'], o que inclui a propriedade não enumerável de uma matriz, 'length' .

Você pode criar suas próprias propriedades não enumeráveis ​​chamando 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'

Este exemplo empresta muito de propriedades Não enumeráveis ​​em JavaScript , mas mostra um objeto sendo enumerado. As propriedades podem ser ou não graváveis, configuráveis ​​ou enumeráveis. John Resig discute isso no escopo do ECMAScript 5 Objects and Properties .

E há uma pergunta de estouro de pilha sobre por que você desejaria tornar as propriedades não enumeráveis .

Carpeliam
fonte
Hm, votos positivos e negativos. Certamente, se houver algo sobre esta resposta que valha a pena votar, adicione um comentário aqui.
Carpeliam
1
Outra resposta escreveu isso: var o = {}; o ['foo'] = 0; // Object.defineProperty normal enumerável (o, 'bar', {value: 1}); // não numerável, estranho Por que adicionar explicitamente enumerável: falso?
287 Patrick
5
@ Patrick, eu o incluí aqui em parte, para que fique claro a partir do exemplo que é uma opção, mas dependendo do seu público, ser explícito pode ser uma decisão sólida apenas para que fique claro para quem está lendo seu código.
Carpeliam
@carpeliam Obrigado por esta explicação curta e muito clara, eu não poderia obter resposta aceita até que eu fui através de sua: D
sandeepKumar
37

É muito mais chato do que algo que deve ser visualizado.

Existe literalmente um atributo em todas as propriedades chamadas "enumeráveis". Quando definido como false, o for..inmétodo pula essa propriedade e finge que não existe.

Existem muitas propriedades em objetos que têm "enumerável" definido como false, como "valueOf" e "hasOwnProperty", porque presume-se que você não queira que o mecanismo JavaScript itere sobre eles.

Você pode criar suas próprias propriedades não enumeráveis ​​usando o Object.definePropertymétodo:

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

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

Agora, o fato de haver um segredo sobre o carro está oculto. É claro que eles ainda podem acessar a propriedade diretamente e obter a resposta:

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

Mas, eles precisariam saber que a propriedade existe primeiro, porque se eles estiverem tentando acessá-la for..inou Object.keyspermanecerão completamente secretos:

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

Eles deveriam ter chamado de "forInAble".

Gabriel Kunkel
fonte
5
Promovido para a última linha - acho que se realmente tivesse sido chamado para InAble, ninguém estaria perguntando sobre isso. O que levanta minha pergunta - por que você (ou por que você precisa) definir uma propriedade para não ser enumerável? A propriedade length de uma matriz é usada frequentemente como exemplo de uma propriedade não enumerável, mas por que você não pode defini-la como enumerável (não a restrição JavaScript, quero dizer, por que foi definida como não enumerável em JavaScript em o primeiro lugar)?
Chris
Para esclarecer minha pergunta, por que foi decidido que o seguinte não era uma opção: marca: Honda modelo: segredo cívico: comprimento do
Chris
Hmmm ... Eu posso ter encontrado a resposta para minha própria pergunta. Em uma pesquisa no Google por "O que você quer dizer com tipos de dados enumerados?" Os dados enumerados possuem um conjunto finito de valores. Um tipo de dados enumerado consiste em valores que você permite para esse tipo ou valores enumerados. Para tipos enumerados baseados em números inteiros, cada valor enumerado consiste em um nome e um valor numérico subjacente.Então, se bem entendi, como há um número infinito de comprimentos possíveis, você teria que atribuir um número infinito de nomes, um nome para cada comprimento. Isso está correto?
Chris
Bem, abordando sua primeira pergunta, definir uma propriedade não enumerável em um objeto é um pouco invasivo, pois a única maneira de descobrir o que estava nesse objeto seria olhar o código e como uma base de código desenvolve que poderia ser enterrado. Então, geralmente, você não gostaria de usá-lo. Quanto ao '.length', que fornece o número de caracteres em uma string ou elementos em uma matriz, é apenas algo que se presume que não desejaríamos incluir se estivéssemos usando 'for ... in'. Não posso responder por que os deuses de Js fizeram dessa maneira necessariamente. Eles têm razões ( ahem ) opiniões além da nossa compreensão.
Gabriel Kunkel
... e acho que não poderia responder à sua segunda pergunta sobre tipos de dados enumerados, embora pareça algo que eu pudesse pensar por algum tempo se tivesse tempo. :-)
Gabriel Kunkel
9

Se você está tendo dificuldades para visualizar "o que significa ser enumerável?" por que não perguntar a si mesmo, o que significa ser inumerável ?

Penso um pouco assim: existe uma propriedade inumerável, mas está parcialmente oculta ; significando que não numerável é o estranho. Agora você pode imaginar enumerável como o que resta - a propriedade mais natural que estamos acostumados a encontrar desde que descobrimos Objetos . Considerar

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

Agora em um for..in, imagine como pseudocódigo

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

onde o corpo do loop digitado em JavaScript está no lugar de/* whatever */

Paul S.
fonte
8

Vou escrever uma definição de linha de ENUMERABLE

Enumerable: Especifica se a propriedade pode ser retornada em um loop for / in.

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

métodos não são enumeráveis; ou melhor, métodos embutidos não são .. depois de pesquisar o que significa numeroso para script java; apenas se refere a um atributo de propriedade .. todos os objetos criados em ecma3 são enumeráveis, e ecma5 agora pode defini-lo .... é isso ..: D lol, demorei um pouco para encontrar a resposta; mas acredito que isso seja discutido no livro de David Flanagan. Acho que significa "oculto" ou não "oculto", pois os métodos não são mostrados no loop for in e, portanto, são "ocultos"

user316264
fonte
0

Pense no tipo de dados enum, apenas uma estrutura de objetos que correspondem a números diferentes. Declarar algo como um enumerável é declarar que corresponde a um número específico, permitindo que seja atribuído um lugar em um Dicionário que represente componentes contáveis ​​de um objeto. Simplificando, tornar um objeto enumerável é o mesmo que dizer ao compilador: "Ei, essa propriedade conta, eu quero ver isso quando procurar dados sobre esse objeto".

Jeshawn Chrite
fonte
0

Os métodos internos herdados pelos objetos não são enumeráveis, mas as propriedades que seu código adiciona aos objetos são enumeráveis, a menos que seja declarado explicitamente

parveen mittal
fonte