Liczba elementów w obiekcie javascript

104

Czy istnieje sposób na pobranie (skądś) liczby elementów w obiekcie javascript? (tj. złożoność w czasie stałym).

Nie mogę znaleźć właściwości ani metody, która pobrałaby te informacje. Jak dotąd mogę myśleć tylko o wykonaniu iteracji przez całą kolekcję, ale to czas liniowy.
To dziwne, że nie ma bezpośredniego dostępu do rozmiaru obiektu, nie sądzisz.

EDYCJA:
mówię o Objectobiekcie (nie o obiektach w ogóle):

var obj = new Object ;
Uwolnić się
źródło
5
Już tu odpowiedzi stackoverflow.com/questions/126100/... Object.keys (obj) .length
spats

Odpowiedzi:

155

Chociaż implementacje JS mogą wewnętrznie śledzić taką wartość, nie ma standardowego sposobu na jej uzyskanie.

W przeszłości, wariant Javascript Mozilli ujawniał niestandardowość__count__ , ale został usunięty w wersji 1.8.5.

W przypadku skryptów między przeglądarkami utkniesz z jawnym iterowaniem właściwości i sprawdzaniem hasOwnProperty():

function countProperties(obj) {
    var count = 0;

    for(var prop in obj) {
        if(obj.hasOwnProperty(prop))
            ++count;
    }

    return count;
}

W przypadku implementacji obsługujących ECMAScript 5, można to również zapisać jako (Kudos to Avi Flax )

function countProperties(obj) {
    return Object.keys(obj).length;
}

Pamiętaj, że przegapisz również właściwości, których nie można wyliczyć (np. Tablice length).

Jeśli używasz frameworka takiego jak jQuery, Prototype, Mootools, $ cokolwiek-najnowszego-hype, sprawdź, czy mają one własne API kolekcji, które może być lepszym rozwiązaniem twojego problemu niż używanie natywnych obiektów JS.

Christoph
źródło
11
Cholera, zawsze zapominam, że ma Własność. Za dużo czasu w krainie .NET mówię ci. +1
annakata
2
jQuery używa obiektu dla swoich kolekcji, które otrzymuje z zapytań, i ujawnia tę wartość za pomocą właściwości length.
Nosredna
6
Firefox4 __count__zniknął :(
Timo Huovinen
1
Czy można to zrobić bez for in? Jestem w tym samym typie wiązania, ale chciałbym, aby przeszedł przez JSLint, jeśli to w ogóle możliwe.
latarnia uliczna
1
dlaczego potrzebujemy hasOwnProperty()?
szwajcarski
100

Aby to zrobić w dowolnym środowisku zgodnym z ES5

Object.keys(obj).length

(Obsługa przeglądarek stąd )
(Dokument na Object.keys tutaj , obejmuje metodę, którą można dodać do przeglądarek innych niż ECMA5)

ZelkiN
źródło
2
To nie jest właściwe pytanie, aby udzielić tej odpowiedzi. W ten sposób bierzesz wszystkie klucze obiektu, umieszczasz je w nowo utworzonej tablicy, a następnie pobierasz właściwość length z tej nowej tablicy.
GetFree
13
Może nie jest najbardziej wydajna programowo, ale jest najbardziej wydajna dla programistów.
superluminium
9

jeśli już używasz jQuery w swojej kompilacji, zrób to:

$(yourObject).length

Działa dobrze dla mnie na obiektach, a jQuery już miałem jako zależność.

Nieusuwalny Heff
źródło
5
Dziwne ... to na mnie nie działa. Zawsze dostaję 1. Odpowiedź ZelkiN działa u mnie.
mike gryzoń
3
Ten kod zawsze zwraca 1. Tylko 1 obiekt. Nie liczy w nim elementów
BeRocket
5
function count(){
    var c= 0;
    for(var p in this) if(this.hasOwnProperty(p))++c;
    return c;
}

var O={a: 1, b: 2, c: 3};

count.call(O);
kennebec
źródło
2

AFAIK, nie ma sposobu, aby to zrobić niezawodnie, chyba że przełączysz się na tablicę. Co szczerze mówiąc, nie wydaje się dziwne - wydaje mi się całkiem proste, że tablice są policzalne, a obiekty nie.

Prawdopodobnie najbliżej otrzymasz coś takiego

// Monkey patching on purpose to make a point
Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this ) i++;
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 3

Ale to stwarza problemy, a przynajmniej pytania. Zliczane są wszystkie właściwości utworzone przez użytkownika, w tym sama funkcja _length! I chociaż w tym prostym przykładzie możesz tego uniknąć, używając zwykłej funkcji, nie oznacza to, że możesz powstrzymać inne skrypty przed zrobieniem tego. więc co robisz? Ignorować właściwości funkcji?

Object.prototype.length = function()
{
  var i = 0;
  for ( var p in this )
  {
      if ( 'function' == typeof this[p] ) continue;
      i++;
  }
  return i;
}

alert( {foo:"bar", bar: "baz"}.length() ); // alerts 2

W końcu myślę, że prawdopodobnie powinieneś porzucić pomysł policzalności swoich obiektów i wymyślić inny sposób robienia tego, co robisz.

Peter Bailey
źródło
8
NIEBEZPIECZEŃSTWO BĘDZIE ROBINSON! Czy nie proto przeciwko obiekt! Wszystko pochodzi od Object, sparaliżujesz przetwarzanie klienta w ten sposób, jeśli wykonujesz znaczną ilość pracy w JS.
annakata
5
Uh ... czy nie przeczytałeś części, w której napisałem w komentarzu „Małpa łata celowo, żeby coś powiedzieć” - daj spokój, zrobiłem to celowo, żeby ludzie się trochę nie przejmowali. Poza tym, mimo że nie jestem zwolennikiem małpich poprawek, źle rozumiesz, jak działa łańcuch prototypów w Javascript, jeśli uważasz, że mogłoby to spowodować problemy z wydajnością video.yahoo.com/watch/111585/1027823
Peter Bailey
Więc .. to jest tak czy nie?
OscarRyz
W „Javascript: The Good Parts” prototypuje obiekt za pomocą metody „create ()”. Wierzę, że to definitywna książka o Javascript.
Chris Dutrow
1

Pojęcie liczby / długości / wymiarowości tak naprawdę nie ma sensu dla obiektu, a potrzeba jej sugeruje, że naprawdę chcesz mieć dla mnie Array.

Edycja: Wskazano mi, że chcesz za to O (1). O ile wiem, obawiam się, że taka droga nie istnieje.

annakata
źródło
Zaproponował powtórzenie się, czym jest to rozwiązanie. Potrzebował sposobu O (1), aby to osiągnąć ...
Thomas Hansen
Masz w zasadzie rację. Naprawdę należy dokładniej czytać pytania.
annakata
Właściwie, obiekty są najbliższe Mapie w JS. Mapy mają długość.
Cristian Vrabie