Co znaczy enumerable?

151

Zostałem skierowany na stronę for..in w MDN, kiedy napisano: „for..in Iteruje po wyliczalnych właściwościach obiektu”.

Następnie przeszedłem do strony Wyliczalność i własność właściwości, na której było napisane: „Wyliczalne właściwości to te, które mogą być iterowane przez pętlę for..in”.

Słownik definiuje wyliczalne jako policzalne, ale tak naprawdę nie mogę sobie wyobrazić, co to oznacza. Czy mogę dostać przykład czegoś, co jest wyliczalne?

Patrick
źródło
Czy rozumiesz, co for-inrobi?
Z odpowiedzi otrzymałem, że for..in pozwala na udostępnienie wszystkich wyliczalnych właściwości obiektu do użycia z instrukcją for
Patrick
6
Najprostsze znaczenie brzmi: czy nieruchomość będzie wytwarzana przez for inpętlę, czy nie (dla tych, którzy nie chcą znać szczegółów lub po prostu nie dbają;))
Tomasz Racia

Odpowiedzi:

158

Wyliczalna właściwość to taka, która może być uwzględniona i odwiedzana podczas for..inpętli (lub podobnej iteracji właściwości, jak np Object.keys().).

Jeśli właściwość nie zostanie zidentyfikowana jako wyliczalna, pętla zignoruje, że znajduje się w obiekcie.

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"

Właściwość jest identyfikowana jako wyliczalna lub nie na podstawie własnego [[Enumerable]]atrybutu . Możesz to zobaczyć jako część deskryptora właściwości :

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 }

Następnie for..inpętla wykonuje iterację po nazwach właściwości obiektu.

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

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

Ale ocenia swoją instrukcję - console.log(prop);w tym przypadku - tylko dla tych właściwości, których [[Enumerable]]atrybutem jest true.

Ten warunek istnieje, ponieważ obiekty mają o wiele więcej właściwości , zwłaszcza z dziedziczenia :

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

Każda z tych właściwości nadal istnieje na obiekcie :

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

Ale są pomijane przez for..inpętlę, ponieważ nie są wyliczalne.

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

console.log(descriptor.enumerable); // false
Jonathan Lonowski
źródło
Zatem właściwość constructor nie jest wyliczalna, ponieważ nie pojawia się w pętli for..in. Podczas gdy nazwy właściwości, takich jak bar lub baz, są wyliczalne, ponieważ udało ci się wyliczyć każdą z nich z obiektu console.log?
Patrick,
5
To nie jest do końca poprawne: But, they are skipped (or not counted) by the for..in loop because they are not enumerable. Właściwości włączone Object.prototypesą w rzeczywistości ignorowane, ponieważ znajdują się dalej w łańcuchu prototypów, a nie dlatego, że nie można ich wyliczyć. Ani getOwnPropertyNames()lub keys()wykazują właściwości, które nie są przedmiotem rękę. Na marginesie, prawdą jest, że wielu wbudowanych właściwości nie jest wyliczalnych i dlatego nie będą one wyświetlane z keys(), ale będziesz musiał napisać dodatkowy kod, jeśli chcesz przejść przez łańcuch prototypów.
Magnus
dosłownie wyliczalne oznacza policzalne
Christian Matthew
49

Jeśli utworzysz obiekt za pośrednictwem myObj = {foo: 'bar'}lub czegoś w pobliżu, wszystkie właściwości są wyliczalne. Więc łatwiejszym pytaniem jest to, czego nie da się wyliczyć? Niektóre obiekty mają pewne niewliczalne właściwości, na przykład jeśli wywołasz Object.getOwnPropertyNames([])(które zwraca tablicę wszystkich właściwości, wyliczalnych lub nie, na []), zwróci ['length'], co zawiera niewliczalną właściwość tablicy, „length” .

Możesz tworzyć własne niewliczalne właściwości, wywołując 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'

Ten przykład w znacznym stopniu zapożycza z niewliczalnych właściwości w JavaScript , ale pokazuje wyliczany obiekt. Właściwości mogą być zapisywalne lub nie, konfigurowalne lub wyliczalne. John Resig omawia to w ramach ECMAScript 5 Objects and Properties .

Jest też pytanie o przepełnienie stosu, dlaczego kiedykolwiek chciałbyś, aby właściwości były niewymierne .

carpeliam
źródło
Hm, głosy za i przeciw. Z pewnością, jeśli w tej odpowiedzi jest coś, co warte jest odrzucenia, dodaj komentarz tutaj.
carpeliam
1
Inna odpowiedź napisała to: var o = {}; o ['foo'] = 0; // wyliczalne, normalne Object.defineProperty (o, 'bar', {wartość: 1}); // niepoliczalne, dziwne Po co jawnie dodawać enumerable: false?
Patrick,
5
@Patrick, zawarłem to tutaj częściowo, aby z przykładu jasno wynikało, że jest to opcja, ale w zależności od odbiorców wyraźna decyzja może być solidną decyzją, aby była jasna dla każdego, kto czyta Twój kod.
carpeliam
@carpeliam Dzięki za to krótkie i bardzo jasne wyjaśnienie, nie mogłem uzyskać zaakceptowanej odpowiedzi, dopóki nie przejrzałem twojej: D
sandeepKumar
37

To o wiele bardziej nudne niż coś, co powinno być wizualizowane.

We wszystkich właściwościach istnieje dosłownie atrybut zwany „wyliczalnym”. Gdy ma wartość false, for..inmetoda pominie tę właściwość, udając, że nie istnieje.

Istnieje wiele właściwości obiektów, które mają ustawioną wartość „enumerable” na false, np. „ValueOf” i „hasOwnProperty”, ponieważ zakłada się, że nie chcesz, aby silnik JavaScript wykonywał iteracje po nich.

Możesz tworzyć własne niewliczalne właściwości przy użyciu Object.definePropertymetody:

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

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

Teraz fakt, że jest nawet sekret dotyczący samochodu, jest ukryty. Oczywiście nadal mogą uzyskać bezpośredni dostęp do nieruchomości i uzyskać odpowiedź:

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

Ale musieliby wiedzieć, że własność istnieje jako pierwsza, ponieważ jeśli próbują uzyskać do niej dostęp, for..inlub Object.keyspozostanie ona całkowicie tajna:

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

Powinni po prostu nazwać to „forInAble”.

Gabriel Kunkel
źródło
5
Głosowano za tą ostatnią linią - myślę, że gdyby faktycznie była nazywana InAble, nikt by o to nie pytał. Pojawia się moje pytanie - dlaczego miałbyś (lub dlaczego miałbyś) ustawić właściwość tak, aby nie była wyliczalna? Właściwość length tablicy jest używana dość często jako przykład niewliczalnej właściwości, ale dlaczego nie można po prostu ustawić jej na wyliczalną (nie ograniczenie JavaScript, mam na myśli, dlaczego została ustawiona na niewliczalna w JavaScript w pierwsze miejsce)?
Chris,
Aby wyjaśnić moje pytanie, dlaczego zdecydowano, że nie ma opcji: marka: model Hondy: tajemnica cywilna : długość
Chris
Hmmm ... Mogłem znaleźć odpowiedź na swoje własne pytanie. Z wyszukiwania Google „Co masz na myśli przez wyliczone typy danych?” Dane wyliczeniowe mają skończony zbiór wartości. Wyliczeniowy typ danych składa się z wartości dozwolonych dla tego typu lub wartości wyliczonych. W przypadku typów wyliczeniowych opartych na liczbach całkowitych każda wyliczana wartość składa się z nazwy i podstawowej wartości liczbowej, więc jeśli dobrze rozumiem, ponieważ istnieje nieskończona liczba możliwych długości, musiałbyś przypisać nieskończoną liczbę nazw, jedną nazwę na każdą długość. Czy to jest poprawne?
Chris,
Cóż, odpowiadając na pierwsze pytanie, ustawienie niewliczalnej właściwości na obiekcie jest trochę skomplikowane, ponieważ jedynym sposobem, aby dowiedzieć się, co było w tym obiekcie, byłoby spojrzenie na kod i jako podstawę kodu rozwinie się, że można go zakopać. Więc generalnie nie chcesz go używać. Odnośnie „.length”, która podaje liczbę znaków w ciągu lub elementów tablicy, jest po prostu czymś, co przypuszczalnie nie chcielibyśmy uwzględnić, gdybyśmy użyli „for ... in”. Nie mogę odpowiedzieć, dlaczego bogowie z J. koniecznie tak to zrobili. Mają powody ( ahem ) opinie poza naszym zrozumieniem.
Gabriel Kunkel
... i nie sądzę, żebym mógł odpowiedzieć na twoje drugie pytanie dotyczące wyliczonych typów danych, chociaż wygląda na to, że mógłbym żuć coś przez dłuższy czas, gdybym miał czas. :-)
Gabriel Kunkel
9

Jeśli masz trudności z wyobrażeniem sobie, „co to znaczy być policzalnym?” dlaczego nie zadać sobie pytania, co to znaczy być niepoliczalnym ?

Myślę o tym trochę w ten sposób, istnieje niezliczona właściwość , która jest częściowo ukryta ; co oznacza, że niepoliczalne jest dziwne. Teraz możesz wyobrazić sobie wyliczenie jako to, co pozostało - tym bardziej naturalną właściwość, z którą się spotykamy, odkąd odkryliśmy Obiekty . Rozważać

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

Teraz w a for..in, wyobraź sobie to jak pseudokod

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

gdzie ciało pętli wpisanej w JavaScript jest w miejscu/* whatever */

Paul S.
źródło
8

Napiszę jedną definicję linii ENUMERABLE

Enumerable: Określa, czy właściwość może zostać zwrócona w pętli for / in.

var obj = {};
Object.defineProperties(obj, {
    set1: {enumerable: true},
    set2: {enumerable: false},
});
Object.keys(obj); // ["set1"]
Object.getOwnPropertyNames(obj); // ["set1", "set2"]
Ved
źródło
0

metody nie są wyliczalne; a raczej metody wbudowane nie są… po wyszukaniu tego, co wyliczalne dla skryptu java; odnosi się tylko do atrybutu własności .. wszystkie utworzone obiekty w ecma3 są wyliczalne, a ecma5 u może teraz je zdefiniować… to wszystko…: D lol trochę mi zajęło znalezienie odpowiedzi; ale wierzę, że jest to omówione w książce Davida Flanagana .. więc myślę, że oznacza to „ukryte” lub „ukryte”, ponieważ metody nie są pokazywane w pętli for in, a zatem są „ukryte”

user316264
źródło
0

Pomyśl o wyliczonym typie danych, tylko o strukturze obiektów, które odpowiadają różnym liczbom. Zadeklarowanie czegoś jako wyliczalnego oznacza zadeklarowanie, że odpowiada on określonej liczbie, pozwalając na nadanie jej miejsca w słowniku, który reprezentuje policzalne składniki obiektu. Mówiąc prościej, uczynienie obiektu wyliczalnym jest tym samym, co powiedzenie kompilatorowi: „Hej, ta właściwość się liczy, chcę to zobaczyć, kiedy sprawdzę dane dotyczące tego obiektu”.

Jeshawn Chrite
źródło
0

Wbudowane metody dziedziczone przez obiekty nie są wyliczalne, ale właściwości, które kod dodaje do obiektów, są wyliczalne, chyba że zostanie to wyraźnie określone

parveen mittal
źródło