Mam obiekt JavaScript podobny do następującego:
var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};
Teraz chcę pętli wszystkich p
elementów ( p1
, p2
, p3
...) i dostać klucze i wartości. Jak mogę to zrobić?
W razie potrzeby mogę zmodyfikować obiekt JavaScript. Moim ostatecznym celem jest przejście przez niektóre pary kluczowych wartości i jeśli to możliwe, chcę uniknąć ich używania eval
.
javascript
loops
for-loop
each
Tanmoy
źródło
źródło
Odpowiedzi:
Możesz użyć
for-in
pętli w sposób pokazany przez innych. Musisz jednak upewnić się, że klucz, który otrzymasz, jest faktyczną właściwością obiektu i nie pochodzi z prototypu.Oto fragment:
For-of with Object.keys () alternatywa:
Zauważ, że użycie
for-of
zamiastfor-in
, jeśli nie zostanie użyte, zwróci niezdefiniowane właściwości o nazwanych właściwościach iObject.keys()
zapewni użycie tylko własnych właściwości obiektu bez właściwości całego łańcucha prototypówUżywając nowej
Object.entries()
metody:Uwaga: Ta metoda nie jest obsługiwana natywnie przez Internet Explorera. Możesz rozważyć użycie funkcji Polyfill w starszych przeglądarkach.
źródło
alert(key + " -> " + JSON.stringify(p[key]));
__proto__
lubprototype
. Ta właściwość ma odwołanie do swojego obiektu nadrzędnego. Obiekt automatycznie dziedziczy właściwość po rodzicu. To jest powód używaniahasOwnProperty
, co oznacza, że interesują nas własność obiektów, a nie ich własności macierzyste.W ECMAScript 5 możesz łączyć
Object.keys()
iArray.prototype.forEach()
:ECMAScript 6 dodaje
for...of
:ECMAScript 8 dodaje,
Object.entries()
że unika się konieczności wyszukiwania każdej wartości w oryginalnym obiekcie:Możesz łączyć
for...of
, niszczyć iObject.entries
:Zarówno
Object.keys()
iObject.entries()
iterują właściwości w tej samej kolejności cofor...in
pętla, ale ignorują łańcuch prototypów . Iterowane są tylko własne wyliczalne właściwości obiektu.źródło
Object.forEach(obj, function (value, key) {...})
? :( Z pewnościąobj.forEach(function...)
byłby krótszy i uzupełniałbyArray.prototype.forEach
, ale ryzykowałoby to tym, że obiekty definiowałyby swojąforEach
własność. Przypuszczam, żeObject.keys
chronią przed wywołaniem zwrotnym modyfikującym klucze obiektu.Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))
([klucz, wartość] oznacza rozkład tablic, aby uzyskać bezpośredni dostęp do obu elementów. I trzeba zawinąć parametry w dodatkowe pareny.)index
klucz w Json? Czy w razie potrzeby powinienem użyć osobnego licznika?for...of
jest standardem ES6, a nie ES2016.Musisz użyć pętli for-in
Należy jednak zachować ostrożność podczas korzystania z tego rodzaju pętli, ponieważ spowoduje to zapętlenie wszystkich właściwości wzdłuż łańcucha prototypów .
Dlatego podczas korzystania z pętli wejściowych zawsze używaj
hasOwnProperty
metody, aby ustalić, czy bieżąca właściwość w iteracji jest rzeczywiście własnością obiektu, który sprawdzasz:źródło
{ }
osobiście, ponieważif
bez nich trochę niejasne jest, co jest częścią,if
a co nie. Ale myślę, że to tylko kwestia opinii :){ }
głównie, aby uniknąć nieporozumień, jeśli później trzeba coś dodać doif
zakresu.Object.prototype.hasOwnProperty.call(p, prop)
Jednak to też nie może ochronić przed manipulacjami na Object.prototype ...Pytanie nie będzie kompletne, jeśli nie wspomnimy o alternatywnych metodach zapętlania obiektów.
Obecnie wiele dobrze znanych bibliotek JavaScript udostępnia własne metody iteracji po kolekcjach, tj. Tablicach , obiektach i obiektach podobnych do tablic . Te metody są wygodne w użyciu i są w pełni kompatybilne z dowolną przeglądarką.
Jeśli pracujesz z jQuery , możesz użyć
jQuery.each()
metody. Można go używać do płynnego iterowania zarówno obiektów, jak i tablic:W Underscore.js można znaleźć metodę
_.each()
, która iteruje po liście elementów, dając z kolei każdy z dostarczonych funkcji (zwróć uwagę na kolejność argumentów w funkcji iteracji !):Lo-Dash zapewnia kilka metod iteracji właściwości obiektu. Podstawowy
_.forEach()
(lub jego alias_.each()
) jest przydatny do przechodzenia między obiektami i tablicami, jednak (!) Obiekty zlength
właściwością są traktowane jak tablice i aby uniknąć tego zachowania, sugeruje się użycie_.forIn()
i_.forOwn()
metody (te mają równieżvalue
argument na początku):_.forIn()
iteruje nad własnymi i odziedziczonymi wyliczalnymi właściwościami obiektu, podczas gdy_.forOwn()
iteruje tylko nad własnymi właściwościami obiektu (w zasadzie sprawdzeniehasOwnProperty
funkcji). W przypadku prostych obiektów i literałów obiektowych dowolna z tych metod będzie działać poprawnie.Ogólnie wszystkie opisane metody zachowują się tak samo z dowolnymi dostarczonymi obiektami. Poza tym użycie
for..in
pętli rodzimej będzie zwykle szybsze niż jakakolwiek abstrakcja, na przykładjQuery.each()
metody te są znacznie łatwiejsze w użyciu, wymagają mniej kodowania i zapewniają lepszą obsługę błędów.źródło
W ECMAScript 5 masz nowe podejście do iteracji w dosłowności -
Object.keys
Więcej informacji można znaleźć w MDN
Mój wybór jest poniżej jako szybsze rozwiązanie w obecnych wersjach przeglądarek (Chrome30, IE10, FF25)
Możesz porównać wydajność tego podejścia z różnymi implementacjami na jsperf.com :
Obsługa przeglądarek widoczna w tabeli kompatybilności Kangaxa
W przypadku starej przeglądarki masz prosty i pełny pakiet wypełniający
UPD:
porównanie wydajności dla wszystkich najpopularniejszych przypadków w tym pytaniu na
perfjs.info
:iteracja dosłowna obiektu
źródło
Przedmowa:
Tutaj w 2018 r. Masz opcje do przechodzenia między właściwościami obiektu (niektóre przykłady znajdują się na liście):
for-in
[ MDN , spec ] - Struktura pętli, która przechodzi przez nazwy właściwości wyliczalnych obiektu , w tym odziedziczonych, których nazwy są łańcuchamiObject.keys
[ MDN , spec ] - Funkcja udostępniająca tablicę nazw własnych , policzalnych właściwości obiektu, których nazwy są łańcuchami.Object.values
[ MDN , Spec ] - funkcja zapewnienia tablicę wartości obiektu na własnych , przeliczalnych właściwości.Object.entries
[ MDN , spec ] - Funkcja zapewniająca tablicę nazw i wartości własnych , wyliczalnych właściwości obiektu (każda pozycja w tablicy jest[name, value]
tablicą).Object.getOwnPropertyNames
[ MDN , spec ] - Funkcja udostępniająca tablicę nazw własnych właściwości obiektu (nawet niepoliczalnych), których nazwy są łańcuchami.Object.getOwnPropertySymbols
[ MDN , spec ] - Funkcja udostępniająca tablicę nazw własnych właściwości obiektu (nawet niepoliczalnych), których nazwy to Symbole.Reflect.ownKeys
[ MDN , spec ] - Funkcja udostępniająca tablicę nazw własnych właściwości obiektu (nawet tych niepoliczalnych), niezależnie od tego, czy są to ciągi znaków, czy symbole.Object.getPrototypeOf
[ MDN , Spec ] i za pomocąObject.getOwnPropertyNames
,Object.getOwnPropertySymbols
alboReflect.ownKeys
na każdy obiekt w łańcuchu prototypu (przykład na dole tej odpowiedzi).Ze wszystkich z wyjątkiem
for-in
, można by użyć jakiegoś zapętlenie konstrukt na tablicy (for
,for-of
,forEach
, itd.).Przykłady:
for-in
:Pokaż fragment kodu
Object.keys
(zfor-of
pętlą, ale można użyć dowolnej konstrukcji pętli) :Pokaż fragment kodu
Object.values
:Pokaż fragment kodu
Object.entries
:Pokaż fragment kodu
Object.getOwnPropertyNames
:Pokaż fragment kodu
Object.getOwnPropertySymbols
:Pokaż fragment kodu
Reflect.ownKeys
:Pokaż fragment kodu
Wszystkie właściwości , w tym odziedziczone niewymienne:
Pokaż fragment kodu
źródło
Możesz po prostu iterować:
Pamiętaj, że
key
nie przyjmuje wartości właściwości, jest to tylko wartość indeksu.źródło
Ponieważ es2015 staje się coraz bardziej popularny, zamieszczam tę odpowiedź, która obejmuje użycie generatora i iteratora do płynnego iterowania
[key, value]
par. Jak to możliwe w innych językach, na przykład Ruby.Ok, oto kod:
Wszystkie informacje o tym, jak wykonać iterator i generator, można znaleźć na stronie programisty Mozilla.
Mam nadzieję, że to komuś pomogło.
EDYTOWAĆ:
ES2017 będzie zawierać,
Object.entries
co[key, value]
jeszcze bardziej ułatwi iterację par w obiektach. Obecnie wiadomo, że będzie to część standardu zgodnie z informacją o etapie ts39 .Myślę, że czas zaktualizować moją odpowiedź, aby stała się jeszcze bardziej świeża niż obecnie.
Więcej informacji na temat użytkowania można znaleźć na stronie MDN
źródło
Uwaga: możesz to zrobić na tablicach, ale będziesz iterował także
length
i inne właściwości.źródło
key
po prostu przyjmie wartość indeksu, aby tylko ostrzec 0, 1, 2 itd. ... Musisz uzyskać dostęp do p [klucz].var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }
„p1” i „p2”, więc co w tym złego?Po przejrzeniu wszystkich odpowiedzi tutaj, hasOwnProperty nie jest wymagane do własnego użytku, ponieważ mój obiekt json jest czysty; naprawdę nie ma sensu dodawać żadnego dodatkowego przetwarzania javascript. To wszystko, czego używam:
źródło
Object.prototype
włączy właściwość , zostanie ona wyliczona przezfor..in
. Jeśli masz pewność, że nie korzystasz z żadnych bibliotek, które to robią, nie musisz dzwonićhasOwnProperty
.Object.create(null)
poprzez prototyp za pomocą forEach (), który powinien pominąć właściwości łańcucha prototypów :
źródło
obj = { print: 1, each: 2, word: 3 }
produkujeTypeError: number is not a function
. Używanie wforEach
celu dopasowania podobnejArray
funkcji może nieco zmniejszyć ryzyko.To ciekawe, ludzie w tych odpowiedziach dotknął zarówno
Object.keys()
afor...of
jednak nigdy ich łączy:Nie można po prostu ponieważ nie jest iterator i czy ing jest brzydki / nieefektywne. Cieszę się, że większość ludzi powstrzymuje się od (z lub bez sprawdzania ), ponieważ jest to również trochę niechlujne, więc poza moją odpowiedzią powyżej, jestem tutaj, aby powiedzieć ...
for...of
Object
for...index
.forEach()
Object.keys()
for...in
.hasOwnProperty()
Możesz iterować zwykłe powiązania obiektów! Zachowując się jak
Map
s przy bezpośrednim użyciu fantazyjnegofor...of
DEMO działającego w Chrome i FF (zakładam tylko ES6)
Tak długo, jak podasz mój podkładkę poniżej:
Bez konieczności tworzenia prawdziwego obiektu mapy, który nie ma miłego cukru syntaktycznego.
W rzeczywistości przy tym podkładce dystansowej, jeśli nadal chciałbyś skorzystać z innej funkcjonalności Mapy (bez odgradzania ich wszystkich), ale nadal chciałeś używać schludnej notacji obiektowej, ponieważ obiekty są teraz iterowalne, możesz teraz po prostu stworzyć z nich Mapę!
Dla tych, którzy nie lubią się bawić, lub
prototype
w ogóle nie zadzierać , możesz zamiast tego ustawić funkcję okna, nazywając to tak jakgetObjIterator()
wtedy;Teraz możesz po prostu wywołać to jako zwykłą funkcję, nic więcej nie ma wpływu
lub
Nie ma powodu, dla którego to by nie działało.
Witamy w przyszłości.
źródło
For those who don't like to shim, or mess with prototype in general, feel free to make the function on window instead, calling it something like getObjIterator() then;
ordinaryObject
dla podkreślenia, że magia nadal działa dla tych typów). Czy sprawdziłeś wersje demo; co ci nie działa, @ noɥʇʎԀʎzɐɹƆ? (PS twoje zdjęcie profilowe z SE to szef)Daje to taką samą listę kluczy, jaką zamierzasz, testując każdy klucz obiektu za pomocą hasOwnProperty. Ta dodatkowa operacja testowa nie
Object.keys( obj ).forEach(function( key ){})
jest potrzebna i powinna być szybsza. Udowodnijmy to:W moim Firefoksie mam następujące wyniki
PS. w Chrome różnica jest jeszcze większa http://codepen.io/dsheiko/pen/JdrqXa
PS2: W ES6 (EcmaScript 2015) możesz iterować ładniej obiekt iterowalny:
źródło
of
bez tworzeniaMap
sOto kolejna metoda iteracji po obiekcie.
źródło
for
metoda może być bardziej wydajna.źródło
Możesz także użyć Object.keys () i iterować po obiektowych kluczach jak poniżej, aby uzyskać wartość:
źródło
Tylko kod JavaScript bez zależności:
źródło
Object.keys()
Zwraca tablicę własnych właściwości przeliczalnych danego obiektu. Przeczytaj więcej na ten temat tutajźródło
Wydajność
Dzisiaj 2020.03.06 Przeprowadzam testy wybranych rozwiązań na Chrome v80.0, Safari v13.0.5 i Firefox 73.0.1 na MacOs High Sierra v10.13.6
Wnioski
for-in
(A, B) są szybkie (lub najszybsze) dla wszystkich przeglądarek dla dużych i małych obiektówfor-of
(H) rozwiązanie szybko nakłada chrom na małe i duże obiektyi
(J, K) są dość szybkie we wszystkich przeglądarkach dla małych obiektów (dla Firefox również szybkie dla dużych ojbects, ale średnio szybkie w innych przeglądarkach)Detale
Przeprowadzono testy wydajności dla
Poniżej fragmenty przedstawiają zastosowane rozwiązania
Pokaż fragment kodu
A oto wyniki dla małych obiektów na chromie
źródło
Możesz dodać prostą funkcję forEach do wszystkich obiektów, dzięki czemu możesz automatycznie zapętlać dowolny obiekt:
Dla tych, którzy nie lubią metody „ za ... za ”:
Teraz możesz po prostu zadzwonić:
Jeśli nie chcesz wywoływać konfliktów z innymi metodami forEach, możesz nazwać je swoją unikalną nazwą.
źródło
Object
) jest ogólnie uważane za anty-wzorzec, ponieważ może łatwo powodować konflikty z innym kodem. Dlatego nie polecam robić tego w ten sposób.Pętle mogą być bardzo interesujące przy użyciu czystego JavaScript. Wygląda na to, że tylko ECMA6 (nowa specyfikacja JavaScript 2015) ma kontrolę nad pętlami. Niestety, kiedy to piszę, zarówno przeglądarki, jak i popularne zintegrowane środowisko programistyczne (IDE) wciąż mają trudności z obsługą całkowicie nowych dzwonków i gwizdków.
Oto, jak wygląda pętla obiektów JavaScript przed ECMA6:
Wiem też, że to pytanie jest poza zakresem tego pytania, ale w 2011 r. ECMAScript 5.1 dodał
forEach
metodę tylko dla tablic, która w zasadzie stworzyła nowy, ulepszony sposób zapętlania tablic, pozostawiając nie iterowalne obiekty ze starą pełną i mylącąfor
pętlą. Dziwne jest jednak to, że ta nowaforEach
metoda nie obsługuje,break
co doprowadziło do różnego rodzaju innych problemów.Zasadniczo w 2011 roku nie ma naprawdę solidnego sposobu zapętlenia w JavaScript poza tym, co wiele popularnych bibliotek (jQuery, Underscore itp.) Postanowiło ponownie wdrożyć.
Począwszy od 2015 roku, mamy teraz lepszy gotowy do zapętlenia sposób na zapętlenie (i rozbicie) dowolnego typu obiektu (w tym tablic i ciągów). Oto, jak ostatecznie będzie wyglądać pętla w JavaScript, kiedy rekomendacja stanie się głównym nurtem:
Pamiętaj, że większość przeglądarek nie będzie obsługiwać powyższego kodu od 18 czerwca 2016 r. Nawet w Chrome musisz włączyć tę specjalną flagę, aby działała:
chrome://flags/#enable-javascript-harmony
Dopóki nie stanie się to nowym standardem, stara metoda może być nadal używana, ale istnieją również alternatywy w popularnych bibliotekach, a nawet lekkie alternatywy dla tych, którzy nie korzystają z żadnej z tych bibliotek.
źródło
Uncaught TypeError: Object.entries is not a function
. Czy to jeszcze nie jest zaimplementowane w chrome?W ES6 mamy dobrze znane symbole do ujawnienia niektórych wcześniej wewnętrznych metod, możesz go użyć do zdefiniowania działania iteratorów dla tego obiektu:
da to taki sam wynik jak użycie for ... w pętli es6.
Ale ważne jest, aby znać możliwości, które masz teraz za pomocą es6!
źródło
Object.keys()
i przydzielonej w pamięci ... Cool!Zrobiłbym to raczej niż sprawdzanie
obj.hasOwnerProperty
w każdejfor ... in
pętli.źródło
źródło
json = [{"key1":"value1","key2":"value2"},{"key1":"value3","key2":"value4"}] for (var i = 0; i < json.length; i++) { for (var key in json[i]) { if (json[i].hasOwnProperty(key)) { console.log(key + " -> " + json[i][key]); } } }
Korzystanie z
for-of
ONObject.keys()
Lubić:
źródło
Jeśli chcesz również wykonać iterację właściwości niepoliczalnych , możesz użyć,
Object.getOwnPropertyNames(obj)
aby zwrócić tablicę wszystkich właściwości (policzalnych lub nie) znalezionych bezpośrednio na danym obiekcie.źródło
Error
obiektu i nie mogłem uzyskać właściwości w pętli lub_.forIn(err)
wywołaniu. UżywanieObject.getOwnPropertyNames(err)
pozwoliło mi uzyskać dostęp do wszystkich części, doError
których wcześniej nie mogłem się dostać. Dzięki!Jeśli ktoś potrzebuje pętli przez obiekty obiektowe z warunkiem :
źródło
Biorąc pod uwagę ES6, chciałbym dodać własną łyżkę cukru i podać jeszcze jedno podejście do iteracji właściwości obiektu.
Ponieważ zwykły obiekt JS nie daje się iterować po wyjęciu z pudełka, nie możemy używać
for..of
pętli do iteracji nad jego zawartością. Ale nikt nie może nas powstrzymać, aby umożliwić iterację .Mamy
book
obiekt.Odkąd go stworzyliśmy, możemy go używać w następujący sposób:
Lub jeśli znasz moc generatorów ES6 , więc z pewnością możesz skrócić kod powyżej.
Jasne, możesz zastosować takie zachowanie do wszystkich obiektów, umożliwiając
Object
iterację naprototype
poziomie.Ponadto obiekty zgodne z iterowalnym protokołem mogą być używane z nowym operatorem rozprzestrzeniania funkcji ES2015 , dzięki czemu możemy odczytać wartości właściwości obiektu jako tablicę.
Można też użyć destructuring zadanie:
Możesz sprawdzić JSFiddle z całym kodem, który podałem powyżej.
źródło
od ES06 możesz pobrać wartości obiektu jako tablicę
zwraca tablicę wartości obiektów i nie wyodrębnia wartości z Prototypu !!
MDN DOCS Object.values ()
i dla kluczy (już tutaj przede mną odebrano)
źródło
W najnowszym skrypcie ES możesz zrobić coś takiego:
źródło