Iteruj przez właściwości obiektu

2038

var obj = {
    name: "Simon",
    age: "20",
    clothing: {
        style: "simple",
        hipster: false
    }
}

for(var propt in obj){
    console.log(propt + ': ' + obj[propt]);
}

W jaki sposób zmienna proptreprezentuje właściwości obiektu? To nie jest wbudowana metoda ani właściwość. Dlaczego wymyśla każdą właściwość w obiekcie?

Rafay
źródło
11
if (typeof(obj[propt]) === 'object') {/ * Zrób to ponownie * /}
noob
13
Naprawdę przepraszam za to pytanie. Wiem, co to jest pętla, nie mogłem się skupić na „zapętlaniu właściwości obiektu”, co, jak sądzę, zostało teraz wyczyszczone. Ponadto polecili mi „JavaScript krok po kroku 2. edycja - Steve Suehring w szkole.
Rafay,
242
To dobre pytanie dla początkujących. Dodam, że mam 15-letnie doświadczenie zawodowe w innych językach i potrzebowałem tej odpowiedzi. Dodałbym 2000, gdybym mógł.
Nathan C. Tresch
60
Szalony, ale odwiedzam tę stronę co kilka miesięcy od lat, aby ponownie nauczyć się składni, jak to zrobić. Nie zawracam sobie głowy pamiętaniem, jak to zrobić ... Po prostu pamiętam, że ta strona jest zawsze dostępna na SO.
HDave
14
To najdziwniejsza strona, którą widziałem na StackOverflow. Jeśli uważnie przeczytasz pytanie, tylko jedna odpowiedź zacznie próbować odpowiedzieć na to, o co faktycznie pytano, i ma wynik -6. Odpowiedź o najwyższym wyniku, która została zaakceptowana, nie tylko nie odpowiada, ale jest po prostu błędna.

Odpowiedzi:

2425

Iteracja po właściwościach wymaga tej dodatkowej hasOwnPropertykontroli:

for (var prop in obj) {
    if (Object.prototype.hasOwnProperty.call(obj, prop)) {
        // do stuff
    }
}

Jest to konieczne, ponieważ prototyp obiektu zawiera dodatkowe właściwości obiektu, które technicznie są jego częścią. Te dodatkowe właściwości są dziedziczone z podstawowej klasy obiektowej, ale nadal są właściwościami obj.

hasOwnProperty po prostu sprawdza, czy jest to właściwość specyficzna dla tej klasy, a nie dziedziczona z klasy podstawowej.


Możliwe jest również wywołanie hasOwnPropertysamego obiektu:

if (obj.hasOwnProperty(prop)) {
    // do stuff
}

Ale to się nie powiedzie, jeśli obiekt ma niepowiązane pole o tej samej nazwie:

var obj = { foo: 42, hasOwnProperty: 'lol' };
obj.hasOwnProperty('foo');  // TypeError: hasOwnProperty is not a function

Dlatego bezpieczniej jest Object.prototypezamiast tego zadzwonić :

var obj = { foo: 42, hasOwnProperty: 'lol' };
Object.prototype.hasOwnProperty.call(obj, 'foo');  // true
Lambda Fairy
źródło
21
@BT Zgodnie z dokumentacją Mozilli : „Jeśli chcesz wziąć pod uwagę tylko właściwości dołączone do samego obiektu, a nie jego prototypów, użyj getOwnPropertyNames lub wykonaj sprawdzenie hasOwnProperty (można również użyć propertyIsEnumerable).”
davidmdem
3
Jaki jest sens dzwonienia object.hasOwnProperty()? Czy fakt, że propertyma jakąkolwiek wartość, nie sugeruje, że jest w tym object?
Alex S
6
Ponieważ, Alex S, prototyp obiektu zawiera dodatkowe właściwości dla obiektu, które technicznie są częścią obiektu. Są dziedziczone z podstawowej klasy obiektowej, ale nadal są właściwościami. hasOwnProperty sprawdza po prostu, czy jest to właściwość specyficzna dla tej klasy, a nie dziedziczona z klasy podstawowej. Dobre wyjaśnienie: brianflove.com/2013/09/05/javascripts-hasownproperty-method
Kyle Richter
87
Wydaje mi się jednak, że powinienem wspomnieć, że Object.keys (obj) jest teraz znacznie lepszym rozwiązaniem do uzyskiwania kluczy do samego obiektu. Link do dokumentacji Mozilli: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Kyle Richter
9
Brakuje jednej ważnej informacji. propertyjest tutaj ciągiem, powinien był zostać wywołany propertyName. W przeciwnym razie może powodować zamieszanie dla początkujących JS, takich jak ja, tj. Co robić wewnątrz if.
Neolisk
1135

Począwszy od JavaScript 1.8.5, można użyć, Object.keys(obj)aby uzyskać tablicę właściwości zdefiniowanych w samym obiekcie (tych, które zwracają wartość true obj.hasOwnProperty(key)).

Object.keys(obj).forEach(function(key,index) {
    // key: the name of the object key
    // index: the ordinal position of the key within the object 
});

Jest to lepsze (i bardziej czytelne) niż użycie pętli for-in.

Jest obsługiwany w tych przeglądarkach:

  • Firefox (Gecko): 4 (2.0)
  • Chrome: 5
  • Internet Explorer: 9

Zobacz Mozilla Developer Network Object.keys () „s odniesienia w celu uzyskania dalszych informacji.

Danny R.
źródło
7
Jest to teraz szerzej obsługiwane: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Dom Vinyard
3
A jeśli potrzebujesz pomocy dla starych przeglądarek, możesz skorzystać z tej funkcji wypełniania
KyleMit
27
W środowiskach, które obsługują ten konstrukt języka, ta metoda pozwala na wywołanie Array.foreach: Object.keys(myObject).forEach(function(key,index) { //key = the name of the object key //index = the ordinal position of the key within the object });
Todd Price
4
@ AJ_83 Nie ma dobrego sposobu na wyrwanie się z forEach (). W tym przypadku użyj trochę () i zwróć true, aby przełamać
Daniel Z.
11
dlaczego jest to bardziej czytelne niż dla? for candidate in candidateStatus... wydaje mi się czytelny
Jona
308

Dziewczęta i chłopaki, jesteśmy w 2019 roku i nie mamy zbyt wiele czasu na pisanie ... Zróbmy więc ten nowy, fajny nowy ECMAScript 2016:

Object.keys(obj).forEach(e => console.log(`key=${e}  value=${obj[e]}`));
Frank Roth
źródło
17
Czym różni się to od odpowiedzi Danny'ego R?
krillgar
27
Jest oneliner i używa mapy zamiast forEach. Również satysfakcja z konsoli.log może być interesująca dla niektórych osób.
Frank Roth,
Satly, to nie działa, gdy obj=window.performance.memory: - / Where as for indoes. tj.var obj = window.performance.memory; for( key in obj ) console.log( 'key=' + key + ' val=' + obj[key] );
Michał
2
window.performance.memoryjest obsługiwany tylko przez chrome i Object.keys(obj)zwraca pustą tablicę. To nie ma nic wspólnego .map.
Frank Roth,
W przypadku, gdy ktoś nie chce przeszukiwać struktury tego single-linera, aby robić więcej niż jedną rzecz naraz e, opublikowałem tę treść. Zasadniczo jest tak, jak większość implementacji skrótu i ​​używa ( (key) => (value) )zamiast niego { key => value }, ale jeśli wcześniej nie musiałeś
kayleeFrye_onDeck
216

Jest to for...in statement( MDN , specyfikacja ECMAScript ).

Można go odczytać jako „ za każdym własności W tym objobiekcie, przypisać każdy obiekt do PROPT zmiennej z kolei”.

Marc B.
źródło
1
Wielkie dzięki, teraz to rozumiem. Waliłem głową, przeglądałem książki i Google.
Rafay
21
Zgadzam się z @RightSaidFred, do inoperatora i foroświadczenia nie są zaangażowane w tym wszystkim, for-inzestawienie przedstawia produkcję gramatyki na własną rękę: for ( LeftHandSideExpression in Expression ),for ( var VariableDeclarationNoIn in Expression )
CMS
2
Dziwna odpowiedź ma tak wiele głosów, zwłaszcza że te popularne komentarze wydają się temu zaprzeczać.
Doug Molineux,
9
Dlaczego jest to oznaczone jako odpowiedź? Jest to prawdopodobnie prawdopodobnie najmniej pomocny w tym wątku ..
computrius
3
Najmniej pomocna odpowiedź? Zależy, jak myślisz, o co OP chciał; kiedy po raz pierwszy przeczytałem pytanie, wydawało się, że to zdumienie wywołane mechanizmem, za pomocą którego zmienna może być używana do sprawdzania właściwości obiektu, i które ta odpowiedź wyjaśnia w sposób wymowny (niezależnie od błędnego określenia „for-in”). Na pytanie „Dlaczego to wymyślić każdej nieruchomości” Widzę mogłyby sugerować PO szukał hasOwnProperty ale nie wie, ale myślę, że to jest bardziej prawdopodobne, to było to, co PO chciała wiedzieć, i błędnie przyjął prawidłowe odpowiedz na inne pytanie. :-)
Wyboisty
157

W aktualnych implementacjach ES możesz użyć Object.entries:

for (const [key, value] of Object.entries(obj)) { }

lub

Object.entries(obj).forEach(([key, value]) => ...)

Jeśli chcesz po prostu iterować po wartościach, użyj Object.values:

for (const value of Object.values(obj)) { }

lub

Object.values(obj).forEach(value => ...)
OneHoopyFrood
źródło
byłoby to najlepsze rozwiązanie (object.entries ...), ale nie mogę go użyć. Jeśli chcesz to zrobić wiele razy i nie możesz obsługiwać tego w swoim frameworku, możesz skorzystać z funkcji wypełniania na tej stronie: developer.mozilla.org/nl/docs/Web/JavaScript/Reference/…
Mario
Trzecia sugestia jest świetna, jeśli tylko wartości właściwości. Niesamowite!
Ginzburg,
27

Jeśli twoje środowisko obsługuje ES2017 , poleciłbym Object.entries :

Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`);
});

Jak pokazano w dokumentacji Mozillas Object.entries () :

Metoda Object.entries () zwraca tablicę par własnych właściwości wyliczalnych danego obiektu [klucz, wartość] w tej samej kolejności, jaką zapewnia pętla for ... in (różnica polega na tym, że pętla for-in wylicza właściwości również w łańcuchu prototypów).

Zasadniczo za pomocą Object.entries możemy zrezygnować z następującego dodatkowego kroku, który jest wymagany w przypadku starszych pętli for ... in :

// This step is not necessary with Object.entries
if (object.hasOwnProperty(property)) {
  // do stuff
}
JSON C11
źródło
22

jquery pozwala teraz to zrobić:

$.each( obj, function( key, value ) {
  alert( key + ": " + value );
});
Rob Sedgwick
źródło
1
$.each({foo:1, length:0, bar:2}, function(k,v){console.log(k,v)})$ .each nie jest odpowiedni dla obiektów. Jeśli obiekt ma właściwość length, a jego wartość wynosi zero, cały obiekt jest traktowany tak, jakby był pustą tablicą.
Bob Stein
Szczegóły, dlaczego uważam, że jest to podejście zachęcające do zgłaszania błędów .
Bob Stein
21

Odpowiedź Dominika jest idealna, po prostu wolę to zrobić w ten sposób, ponieważ łatwiej jest przeczytać:

for (var property in object) {
    if (!object.hasOwnProperty(property)) continue;

    // Do stuff...
}
Cyryl N.
źródło
Powinien być Objectz wielkimi literami o, nie?
Jonathan
18

Powyższe odpowiedzi są nieco irytujące, ponieważ nie wyjaśniają, co robisz wewnątrz pętli for po upewnieniu się, że jest to obiekt: NIE DOSTĘPUJEŚ BEZPOŚREDNIO! W rzeczywistości dostarczono tylko KLUCZ, który należy złożyć do OBJ:

var obj = {
  a: "foo",
  b: "bar",
  c: "foobar"
};

// We need to iterate the string keys (not the objects)
for(var someKey in obj)
{
  // We check if this key exists in the obj
  if (obj.hasOwnProperty(someKey))
  {
    // someKey is only the KEY (string)! Use it to get the obj:
    var myActualPropFromObj = obj[someKey]; // Since dynamic, use [] since the key isn't literally named "someKey"

    // NOW you can treat it like an obj
    var shouldBeBar = myActualPropFromObj.b;
  }
}

To wszystko jest bezpieczne dla ECMA5. Działa nawet w kiepskich wersjach JS, takich jak Rhino;)

dylanh724
źródło
15

Aby dodać użycie ES2015 Reflect.ownKeys(obj) a także iterację właściwości za pomocą iteratora.

Na przykład:

let obj = { a: 'Carrot', b: 'Potato', Car: { doors: 4 } };

można powtórzyć przez

// logs each key
Reflect.ownKeys(obj).forEach(key => console.log(key));

Jeśli chcesz iterować bezpośrednio po wartościach kluczy obiektu, możesz zdefiniować iterator , podobnie jak domyślne iteratory JavaScipts dla łańcuchów, tablic, tablic maszynowych, mapy i zestawu.

JS spróbuje wykonać iterację za pomocą domyślnej właściwości iteratora, którą należy zdefiniować jako Symbol.iterator.

Jeśli chcesz mieć możliwość iteracji po wszystkich obiektach, możesz dodać go jako prototyp obiektu:

Object.prototype[Symbol.iterator] = function*() { 
    for(p of Reflect.ownKeys(this)){ yield this[p]; }
}

Umożliwiłoby to iterację wartości obiektu z pętlą for ..., na przykład:

for(val of obj) { console.log('Value is:' + val ) }

Uwaga : w momencie pisania tej odpowiedzi (czerwiec 2018 r.) Wszystkie inne przeglądarki, ale IE, obsługują generatory i for...ofiterację za pośrednictwemSymbol.iterator

Dimitar Nikowski
źródło
Chociaż tak naprawdę nie odpowiadasz na pytanie PO, było to dla mnie bardzo pomocne, nie wiedziałem jeszcze o Reflect.
Michiel
15
if(Object.keys(obj).length) {
    Object.keys(obj).forEach(key => {
        console.log("\n" + key + ": " + obj[key]);
    });
}

// *** Explanation line by line ***

// Explaining the bellow line
// It checks if obj has at least one property. Here is how:
// Object.keys(obj) will return an array with all keys in obj
// If there is no keys in obj, it will return empty array = []
// Then it will get it's length, if it has at least one element,
// it's bigger than 0 which evaluates to true and the bellow 
// code will be executed.
// Else means it's length = 0 which evaluates to false
// NOTE: you can use Object.hasOwnProperty() instead of Object.keys(obj).length
if(Object.keys(obj).length) {

    // Explaining the bellow line
    // Just like in the previous line, this returns an array with
    // all keys in obj (because if code execution got here, it means 
    // obj has keys.) 
    // Then just invoke built-in javascript forEach() to loop
    // over each key in returned array and calls a call back function 
    // on each array element (key), using ES6 arrow function (=>)
    // Or you can just use a normal function ((key) { blah blah }).
    Object.keys(obj).forEach(key => {

        // The bellow line prints out all keys with their 
        // respective value in obj.
        // key comes from the returned array in Object.keys(obj)
        // obj[key] returns the value of key in obj
        console.log("\n" + key + ": " + obj[key]);
    });
}
Fouad Boukredine
źródło
3
Witaj, czy możesz dodać więcej informacji o swojej odpowiedzi, pod warunkiem, że tylko kod nie pomoże.
Nicolas,
Cześć @Nicolas Dodałem objaśnienie wiersza po wierszu do kodu. Daj mi znać, jeśli nadal nie jest jasne
Fouad Boukredine,
Ponieważ forEach pomijam puste wartości , myślę, że możesz pozbyć się odpowiedzi „jeśli i po prostu”, tak Object.keys(obj).forEach(e => console.log(`key=${e} value=${obj[e]}`));jak Frank.
Darkproduct,
12

Pętla for ... reprezentuje każdą właściwość w obiekcie, ponieważ jest ona jak pętla for. Zdefiniowałeś propt w pętli for ... wykonując:

    for(var propt in obj){
alert(propt + ': ' + obj[propt]);
}

Pętla for ... iteruje iterowalne wyliczalne właściwości obiektu. Każda zmienna, którą zdefiniujesz lub umieścisz w pętli for ..., zmienia się za każdym razem, gdy przechodzi do następnej iterowanej właściwości. Zmienna w pętli for ... in iteruje przez klucze, ale jej wartość jest wartością klucza. Na przykład:

    for(var propt in obj) {
      console.log(propt);//logs name
      console.log(obj[propt]);//logs "Simon"
    }

Możesz zobaczyć, jak zmienna różni się od wartości zmiennej. Natomiast pętla for ... robi coś przeciwnego.

Mam nadzieję, że to pomoże.

Vappor Washmade
źródło
11
let obj = {"a": 3, "b": 2, "6": "a"}

Object.keys(obj).map((item) => {console.log("item", obj[item])})

// a
// 3
// 2
Philll_t
źródło
1
Jak wspomniano w innych komentarzach, forEachbardziej odpowiednie jest tutaj, ponieważ mapma na celu zwrócenie nowej tablicy z wynikami wywoływania bloku kodu przy każdej iteracji. Ale interesują nas tylko skutki uboczne każdej iteracji, a nie wartość zwracana, dlatego nie potrzebujemy nowej tablicy, która mapnam daje.
Danny
11
Object.keys(obj).forEach(key =>
  console.log(`key=${key} value=${obj[key]}`)
);
Fellow Stranger
źródło
10

Możesz użyć Lodash. Dokumentacja

var obj = {a: 1, b: 2, c: 3};
_.keys(obj).forEach(function (key) {
    ...
});
viktarpunko
źródło
10
Dlaczego, u licha, ta „odpowiedź” ma 10 pozytywnych opinii? Zupełnie nie odpowiada na pytanie. Zaczynam tracić wiarę w inteligencję przeciętnego programisty JS.
developerbmw
1
@developerbmw Rozumiem, że korzystanie z funkcji ES6 jest bardziej właściwe, ale odpowiedziałem rok temu. Podziel się z nami swoimi przemyśleniami, gdy będziesz miał minutę.
viktarpunko
1
Chodzi o to, aby bardziej skoncentrować się na metodach natywnych, zamiast sugerować użytkownikowi dodanie biblioteki wierszy 10000 na swojej stronie. Nie zrozum mnie źle, lubię korzystać z Lodash, ale jest na to czas i miejsce, a to nie to.
9

Twoja forpętla iteruje wszystkie właściwości obiektu obj. proptjest zdefiniowany w pierwszym wierszu pętli for. Jest to ciąg znaków, który jest nazwą właściwości objobiektu. W pierwszej iteracji pętli proptbędzie to „name”.

arb
źródło
9

Obiekty w JavaScript są kolekcjami właściwości i dlatego mogą być zapętlone dla każdej instrukcji.

Powinieneś pomyśleć o objkolekcji kluczowych wartości.


źródło
! z tą ważną różnicą, że te „listy właściwości” mogą mieć nazwy jako klucze, podczas gdy normalne tablice JS mogą mieć tylko liczby jako klucze.
Qqwy
9

Obecnie można przekształcić standardowy obiekt JS w obiekt iterowalny, dodając metodę Symbol.iterator. Następnie możesz użyć for ofpętli i uzyskać dostęp do jej wartości bezpośrednio, a nawet użyć operatora rozkładania na obiekcie. Fajne. Zobaczmy, jak możemy to zrobić:

var o = {a:1,b:2,c:3},
    a = [];
o[Symbol.iterator] = function*(){
                       var ok = Object.keys(this);
                            i = 0;
                       while (i < ok.length) yield this[ok[i++]];
                     };
for (var value of o) console.log(value);
// or you can even do like
a = [...o];
console.log(a);

Redu
źródło
1
Ciekawy sposób na zrobienie tego. Dzięki za function*odkrycie!
Benj
5

Jeśli korzystam z Węzła , polecam:

Object.keys(obj).forEach((key, index) => {
    console.log(key);
});
Justin
źródło
5

Chociaż najwyżej oceniana odpowiedź jest poprawna, oto alternatywny przypadek użycia, tzn. Jeśli iterujesz obiekt i chcesz na końcu utworzyć tablicę. Użyj .mapzamiastforEach

const newObj = Object.keys(obj).map(el => {
    //ell will hold keys 
   // Getting the value of the keys should be as simple as obj[el]
})
iRohitBhatia
źródło
4

Dodając również sposób rekurencyjny:

function iterate(obj) {
    // watch for objects we've already iterated so we won't end in endless cycle
    // for cases like var foo = {}; foo.bar = foo; iterate(foo);
    var walked = [];
    var stack = [{obj: obj, stack: ''}];
    while(stack.length > 0)
    {
        var item = stack.pop();
        var obj = item.obj;
        for (var property in obj) {
            if (obj.hasOwnProperty(property)) {
                if (typeof obj[property] == "object") {
                  // check if we haven't iterated through the reference yet
                  var alreadyFound = false;
                  for(var i = 0; i < walked.length; i++)
                  {
                    if (walked[i] === obj[property])
                    {
                      alreadyFound = true;
                      break;
                    }
                  }
                  // new object reference
                  if (!alreadyFound)
                  {
                    walked.push(obj[property]);
                    stack.push({obj: obj[property], stack: item.stack + '.' + property});
                  }
                }
                else
                {
                    console.log(item.stack + '.' + property + "=" + obj[property]);
                }
            }
        }
    }
}

Stosowanie:

iterate({ foo: "foo", bar: { foo: "foo"} }); 
Ondrej Svejdar
źródło
1
@faiz - patrz moje komentarze, jest to ochrona przed utknięciem w niekończącej się pętli, gdy cyklicznie przechodzisz przez obiekt, który ma cykliczne odwołania
Ondrej Svejdar
3

Pętla for..in tworzy nową zmienną (var someVariable), a następnie przechowuje każdą właściwość danego obiektu w tej nowej zmiennej (someVariable) jedna po drugiej. Dlatego jeśli użyjesz bloku {}, możesz iterować. Rozważ następujący przykład.

var obj = {
     name:'raman',
     hobby:'coding',
     planet:'earth'
     };

for(var someVariable in obj) {
  //do nothing..
}

console.log(someVariable); // outputs planet
Raman Sohi
źródło
Poprawienie tego, biorąc pod uwagę jego prostotę. W moim przypadku użycia muszę sprawdzić wszystkie atrybuty w obiekcie pod kątem niejasnych wartości - NaN, wartości zerowe, niezdefiniowane (były to punkty na wykresie i te wartości uniemożliwiały rysowanie wykresu). Aby uzyskać wartość zamiast nazwy, w pętli wystarczy zrobić obj[someVariable]. Być może powodem, dla którego tak bardzo go oceniano, jest to, że nie jest rekurencyjny. Nie byłoby to odpowiednie rozwiązanie, jeśli masz obiekt o bardzo dobrej strukturze.
Katharine Osborne
@KatharineOsborne, a może dlatego, że następujące zdanie jest nieco tajemnicze: „Dlatego jeśli użyjesz bloku {}, możesz iterować”. Kod mówi więcej niż tekst.
bvdb,
3

Tutaj iteruję każdy węzeł i tworzę znaczące nazwy węzłów. Jeśli zauważysz, instanceOf Array i instanceOf Object właściwie robi to samo (w mojej aplikacji podaję jednak inną logikę)

function iterate(obj,parent_node) {
    parent_node = parent_node || '';
    for (var property in obj) {
        if (obj.hasOwnProperty(property)) {
            var node = parent_node + "/" + property;
            if(obj[property] instanceof Array) {
                //console.log('array: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            } else if(obj[property] instanceof Object){
                //console.log('Object: ' + node + ":" + obj[property]);
                iterate(obj[property],node)
            }
            else {
                console.log(node + ":" + obj[property]);
            }
        }
    }
}

uwaga - inspiruje mnie odpowiedź Ondreja Svejdara. Ale to rozwiązanie ma lepszą wydajność i mniej niejednoznaczne

Faiz Mohamed Haneef
źródło
3

Zasadniczo chcesz zapętlić każdą właściwość w obiekcie.

JSFiddle

var Dictionary = {
  If: {
    you: {
      can: '',
      make: ''
    },
    sense: ''
  },
  of: {
    the: {
      sentence: {
        it: '',
        worked: ''
      }
    }
  }
};

function Iterate(obj) {
  for (prop in obj) {
    if (obj.hasOwnProperty(prop) && isNaN(prop)) {
      console.log(prop + ': ' + obj[prop]);
      Iterate(obj[prop]);
    }
  }
}
Iterate(Dictionary);
HovyTech
źródło
obj(prop)<- TypeError: obj nie jest funkcją
le_m
@le_m my bad. Muszę przypadkowo wyjąć hasOwnPropertyatrybut. Powinno już działać.
HovyTech
2

Chcę dodać do powyższych odpowiedzi, ponieważ możesz mieć inne zamiary niż JavaScript. Obiekt JSON i obiekt JavaScript to różne rzeczy, więc możesz iterować właściwości JSON, korzystając z rozwiązań zaproponowanych powyżej, a następnie być zaskoczonym.

Załóżmy, że masz obiekt JSON, taki jak:

var example = {
    "prop1": "value1",
    "prop2": [ "value2_0", value2_1"],
    "prop3": {
         "prop3_1": "value3_1"
    }
}

Niewłaściwy sposób iteracji poprzez „właściwości”:

function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        recursivelyIterateProperties(jsonObject[prop]);
    }
}

Możesz być zaskoczony widząc rejestrowanie konsoli 0, 1itd gdy iteracja właściwości prop1i prop2iprop3_1 . Te obiekty są sekwencjami, a indeksy sekwencji są właściwościami tego obiektu w JavaScript.

Lepszym sposobem na rekurencyjne iterowanie właściwości obiektu JSON byłoby najpierw sprawdzenie, czy ten obiekt jest sekwencją, czy nie:

function recursivelyIterateProperties(jsonObject) {
    for (var prop in Object.keys(example)) {
        console.log(prop);
        if (!(typeof(jsonObject[prop]) === 'string')
            && !(jsonObject[prop] instanceof Array)) {
                recursivelyIterateProperties(jsonObject[prop]);

            }

     }
}
Jadiel de Armas
źródło
1

Aby jeszcze bardziej zawęzić zaakceptowaną odpowiedź, warto zauważyć, że jeśli utworzysz obiekt za pomocą var object = Object.create(null)a, object.hasOwnProperty(property)to spowoduje wystąpienie błędu typu. Aby być bezpiecznym, musisz wywołać go z prototypu w następujący sposób:

for (var property in object) {
    if (Object.prototype.hasOwnProperty.call(object, property)) {
        // do stuff
    }
}
Konrad Kiss
źródło