Wie kann ich ein JavaScript-Objekt durchlaufen oder auflisten?

2880

Ich habe ein JavaScript-Objekt wie das folgende:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Jetzt möchte ich eine Schleife durch alle pElemente ( p1, p2, p3...) und ihre Schlüssel und Werte erhalten. Wie kann ich das machen?

Ich kann das JavaScript-Objekt bei Bedarf ändern. Mein letztendliches Ziel ist es, einige Schlüsselwertpaare zu durchlaufen, und wenn möglich möchte ich die Verwendung vermeiden eval.

Tanmoy
quelle
9
Ich habe JSON in JavaScript (Objekt) geändert, um eine Verwechslung von Objektliteralen und JSON zu vermeiden.
Felix Kling

Antworten:

4367

Sie können die for-inSchleife wie von anderen gezeigt verwenden. Sie müssen jedoch auch sicherstellen, dass der Schlüssel, den Sie erhalten, eine tatsächliche Eigenschaft eines Objekts ist und nicht vom Prototyp stammt.

Hier ist der Ausschnitt:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " -> " + p[key]);
    }
}

For-of mit Object.keys () Alternative:

var p = {
    0: "value1",
    "b": "value2",
    key: "value3"
};

for (var key of Object.keys(p)) {
    console.log(key + " -> " + p[key])
}

Beachten Sie, dass die Verwendung von for-ofanstelle von for-in, wenn sie nicht verwendet wird, für benannte Eigenschaften undefiniert zurückgibt und Object.keys()sicherstellt, dass nur die eigenen Eigenschaften des Objekts ohne die gesamten Eigenschaften der Prototypkette verwendet werden

Mit der neuen Object.entries()Methode:

Hinweis: Diese Methode wird von Internet Explorer nicht nativ unterstützt. Sie können eine Polyfill für ältere Browser verwenden.

const p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (let [key, value] of Object.entries(p)) {
  console.log(`${key}: ${value}`);
}
Levik
quelle
34
Würde vorschlagen, dass Sie die Alarmlinie nur aus Gründen der Klarheit ändernalert(key + " -> " + JSON.stringify(p[key]));
Steve Midgley
80
Können Sie die Notwendigkeit von hasOwnProperty erklären? Was meinst du mit Prototyp?
Kamaci
331
In Javascript verfügt jedes Objekt über eine Reihe integrierter Schlüssel-Wert-Paare mit Metainformationen. Wenn Sie alle Schlüssel-Wert-Paare für ein Objekt durchlaufen, durchlaufen Sie auch diese. hasOwnPropery () filtert diese heraus.
danieltalsky
57
Eigentlich ist For ... in nicht veraltet. Für jeden ... in ist. Aber ich mag den Begriff Archäologen wirklich ... Ich werde damit anfangen müssen.
Ben Y
17
Jedes Objekt in Javascript (eigentlich ein Schlüssel-Wert-Paar) hat eine Eigenschaft namens __proto__oder prototype. Diese Eigenschaft hat einen Verweis auf das übergeordnete Objekt. Ein Objekt erbt automatisch Eigenschaften von seinem übergeordneten Objekt. Dies ist der Grund für die Verwendung hasOwnProperty, was bedeutet, dass wir an Objekten interessiert sind, die Eigentum besitzen, und nicht an den übergeordneten Objekten.
Zubair Alam
1104

Unter ECMAScript 5 können Sie kombinieren Object.keys()und Array.prototype.forEach():

var obj = { first: "John", last: "Doe" };

Object.keys(obj).forEach(function(key) {
    console.log(key, obj[key]);
});

ECMAScript 6 fügt hinzu for...of:

for (const key of Object.keys(obj)) {
    console.log(key, obj[key]);
}

ECMAScript 8 fügt hinzu, Object.entries()wodurch vermieden wird, dass jeder Wert im Originalobjekt nachgeschlagen werden muss:

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

Sie können kombinieren for...of, destrukturieren und Object.entries:

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

Beide Object.keys()und Object.entries()iterieren Eigenschaften in derselben Reihenfolge wie eine for...inSchleife , ignorieren jedoch die Prototypkette . Es werden nur die eigenen aufzählbaren Eigenschaften des Objekts iteriert.

Axel Rauschmayer
quelle
21
Warum hat der Standard nicht bereitgestellt Object.forEach(obj, function (value, key) {...})? :( Sicherlich obj.forEach(function...)wäre es kürzer und komplementärer Array.prototype.forEach, aber das würde dazu führen, dass Objekte ihre eigene forEachEigenschaft definieren . Ich nehme an Object.keys, dass sie vor dem Rückruf schützen, der die Schlüssel des Objekts ändert.
David Harkness
7
Object.forEach = function (obj, callback) { Object.keys(obj).forEach(function (key) { callback(obj[key], key); }); }
David Harkness
7
@ DavidHarkness In ES2017 gibt es Object.entries. Dort können Sie Folgendes tun: Object.entries(obj).map/forEach(([key, value]) => console.log(key, value))([Schlüssel, Wert] ist eine Array-Destrukturierung, um direkt auf beide Elemente zuzugreifen. Und Sie müssen die Parameter in zusätzliche Parens einschließen.)
Andreas Linnert
Wie bekomme ich indexden Schlüssel in JSON? Oder sollte ich bei Bedarf einen separaten Zähler verwenden?
Saravanabalagi Ramachandran
3
for...ofist ES6-Standard, nicht ES2016.
Rax Weber
342

Sie müssen die For-In-Schleife verwenden

Seien Sie jedoch sehr vorsichtig, wenn Sie diese Art von Schleife verwenden, da hierdurch alle Eigenschaften entlang der Prototypenkette wiederholt werden .

Verwenden Sie daher bei der Verwendung von For-In-Schleifen immer die hasOwnPropertyMethode, um festzustellen, ob die aktuelle Eigenschaft in der Iteration wirklich eine Eigenschaft des Objekts ist, das Sie überprüfen:

for (var prop in p) {
    if (!p.hasOwnProperty(prop)) {
        //The current property is not a direct property of p
        continue;
    }
    //Do your logic with the property here
}
Andreas Grech
quelle
31
Dies ist besser als die Lösung von levik, da die Hauptlogik nur eine verschachtelte Schleife in zwei sein kann. Erleichtert das Lesen von Code. Obwohl ich die Klammern um die Fortsetzung verlieren würde; sie sind überflüssig.
SystemicPlural
52
Ich würde das nicht { }persönlich entfernen, weil ein ifohne sie es ein wenig unklar macht, was Teil des ist ifund was nicht. Aber ich denke, das ist nur eine
Ansichtssache
34
Ja, ich ziehe es vor, das { }hauptsächlich zu behalten , um Verwirrung zu vermeiden, wenn man später etwas zum ifGeltungsbereich hinzufügen muss .
Andreas Grech
8
Beim Lesen meines vorherigen Kommentars wurde mir klar, dass ich nicht die richtigen Begriffe verwendet habe, weil ich "if scope" sagte. Beachten Sie jedoch, dass JavaScript nur einen Funktionsumfang hat. Was ich eigentlich meinte, war "if block".
Andreas Grech
1
eomeroff, wenn du dir darüber wirklich Sorgen machst, könntest du immer etwas tun wie: Object.prototype.hasOwnProperty.call(p, prop) Aber auch dies kann nicht vor Manipulationen an Object.prototype schützen ...
jordancpaul
252

Die Frage wird nicht vollständig sein, wenn wir keine alternativen Methoden zum Durchlaufen von Objekten erwähnen.

Heutzutage bieten viele bekannte JavaScript-Bibliotheken ihre eigenen Methoden zum Iterieren über Sammlungen, dh über Arrays , Objekte und Array-ähnliche Objekte . Diese Methoden sind bequem zu verwenden und mit jedem Browser vollständig kompatibel.

  1. Wenn Sie mit jQuery arbeiten , können Sie die jQuery.each()Methode verwenden. Es kann verwendet werden, um sowohl Objekte als auch Arrays nahtlos zu durchlaufen:

    $.each(obj, function(key, value) {
        console.log(key, value);
    });
  2. In Underscore.js finden Sie die Methode_.each() , die über eine Liste von Elementen iteriert und jeweils eine bereitgestellte Funktion ergibt (achten Sie auf die Reihenfolge der Argumente in der iteratee- Funktion!):

    _.each(obj, function(value, key) {
        console.log(key, value);
    });
  3. Lo-Dash bietet verschiedene Methoden zum Durchlaufen von Objekteigenschaften. Basic _.forEach()(oder sein Alias _.each()) ist nützlich, um sowohl Objekte als auch Arrays zu durchlaufen. (!) Objekte mit lengthEigenschaften werden jedoch wie Arrays behandelt. Um dieses Verhalten zu vermeiden, wird die Verwendung empfohlen_.forIn()_.forOwn() Methoden und Methoden zu verwenden (für diese steht auch das valueArgument an erster Stelle):

    _.forIn(obj, function(value, key) {
        console.log(key, value);
    });

    _.forIn()iteriert über eigene und geerbte aufzählbare Eigenschaften eines Objekts, während _.forOwn()nur über eigene Eigenschaften eines Objekts iteriert wird (im Grunde genommen gegen die hasOwnPropertyFunktion prüfen ). Für einfache Objekte und Objektliterale funktioniert jede dieser Methoden einwandfrei.

Im Allgemeinen verhalten sich alle beschriebenen Methoden mit allen bereitgestellten Objekten gleich. Außerdem ist die Verwendung einer nativen for..inSchleife normalerweise schneller als jede Abstraktion. jQuery.each()Diese Methoden sind erheblich einfacher zu verwenden, erfordern weniger Codierung und bieten eine bessere Fehlerbehandlung.

Vision
quelle
4
Um zum Wert zu gelangen: $ .each (obj, function (key, value) {console.log (value.title);});
Ravi Ram
2
Nur lustig, wie Unterstrich und jquery Parameter geändert haben :)
ppasler
52

In ECMAScript 5 haben Sie einen neuen Ansatz in Iterationsfeldern von Literal - Object.keys

Weitere Informationen finden Sie auf MDN

Meine Wahl ist unten als schnellere Lösung in aktuellen Versionen von Browsern (Chrome30, IE10, FF25)

var keys = Object.keys(p),
    len = keys.length,
    i = 0,
    prop,
    value;
while (i < len) {
    prop = keys[i];
    value = p[prop];
    i += 1;
}

Sie können die Leistung dieses Ansatzes mit verschiedenen Implementierungen auf jsperf.com vergleichen :

Browserunterstützung finden Sie in der kompatiblen Tabelle von Kangax

Für alte Browser haben Sie eine einfache und vollständige Polyfüllung

UPD:

Leistungsvergleich für alle gängigsten Fälle in dieser Frage zu perfjs.info:

Objektliteraliteration

Pencroff
quelle
In der Tat wollte ich nur diese Methode posten. Aber du hast mich geschlagen :(
Jamie Hutber
50

Vorwort:

  • Objekteigenschaften können eigene (die Eigenschaft befindet sich auf dem Objekt selbst) oder geerbt sein (nicht auf dem Objekt selbst, auf einem seiner Prototypen) sein.
  • Objekteigenschaften können aufzählbar oder nicht aufzählbar sein . Nicht aufzählbare Eigenschaften werden in vielen Aufzählungen / Arrays von Eigenschaften nicht berücksichtigt.
  • Eigenschaftsnamen können Zeichenfolgen oder Symbole sein. Eigenschaften, deren Namen Symbole sind, werden in vielen Eigenschaftsaufzählungen / Arrays nicht berücksichtigt.

Hier im Jahr 2018 haben Sie folgende Möglichkeiten, die Eigenschaften eines Objekts zu durchlaufen (einige Beispiele folgen der Liste):

  1. for-in[ MDN , spec ] - Eine Schleifenstruktur, die die Namen der aufzählbaren Eigenschaften eines Objekts durchläuft , einschließlich der geerbten, deren Namen Zeichenfolgen sind
  2. Object.keys[ MDN , spec ] - Eine Funktion, die ein Array mit den Namen der eigenen , aufzählbaren Eigenschaften eines Objekts bereitstellt , deren Namen Zeichenfolgen sind.
  3. Object.values[ MDN , spec ] - Eine Funktion, die ein Array der Werte der eigenen , aufzählbaren Eigenschaften eines Objekts bereitstellt .
  4. Object.entries[ MDN , spec ] - Eine Funktion, die ein Array mit den Namen und Werten der eigenen , aufzählbaren Eigenschaften eines Objekts bereitstellt (jeder Eintrag im Array ist ein [name, value]Array).
  5. Object.getOwnPropertyNames[ MDN , spec ] - Eine Funktion, die ein Array der Namen der eigenen Eigenschaften eines Objekts (auch nicht aufzählbarer) bereitstellt , deren Namen Zeichenfolgen sind.
  6. Object.getOwnPropertySymbols[ MDN , spec ] - Eine Funktion, die ein Array der Namen der eigenen Eigenschaften eines Objekts (auch nicht aufzählbarer) bereitstellt , deren Namen Symbole sind.
  7. Reflect.ownKeys[ MDN , spec ] - Eine Funktion , um ein Array der Namen eines Objekts bereitstellt eigenen Eigenschaften (auch nicht-enumerable sind), ob diese Namen Strings oder Symbole sind.
  8. Wenn Sie wollen alle von Eigenschaften eines Objekts, einschließlich nicht-zählbaren geerbten, müssen Sie eine Schleife verwenden und Object.getPrototypeOf[ MDN , spec ] und Verwendung Object.getOwnPropertyNames, Object.getOwnPropertySymbolsoder Reflect.ownKeysauf jedes Objekt in der Prototypkette (zB am Ende der Antwort).

Mit alle außer for-in, würden Sie eine Art Looping - Konstrukt auf dem Array (verwenden for, for-of, forEach, etc.).

Beispiele:

for-in::

Object.keys (mit einer for-ofSchleife, aber Sie können jedes Schleifenkonstrukt verwenden) :

Object.values::

Object.entries::

Object.getOwnPropertyNames::

Object.getOwnPropertySymbols::

Reflect.ownKeys::

Alle Eigenschaften , einschließlich geerbter nicht aufzählbarer Eigenschaften :

TJ Crowder
quelle
Schöne Hinzufügung von aufzählbaren / nicht aufzählbaren Objekteigenschaften.
Serraosays
49

Sie können es einfach wie folgt durchlaufen:

for (var key in p) {
  alert(p[key]);
}

Beachten Sie, dass keyder Wert der Eigenschaft nicht angenommen wird, sondern nur ein Indexwert.

Bryan
quelle
13
Dies wird wiederholt und ist nicht einmal ganz richtig. Sie müssen eine Überprüfung von hasOwnProperty haben, damit dies ordnungsgemäß funktioniert
Vatsal
4
Ich habe dies zunächst aufgrund des obigen Kommentars abgelehnt, bis mir klar wurde, dass diese Antwort zuerst kam und daher nicht "wiederholt" wird. Es ist möglicherweise unvollständig, funktioniert aber in vielen Fällen einwandfrei.
Billynoah
27

Da es2015 immer beliebter wird, veröffentliche ich diese Antwort, die die Verwendung von Generator und Iterator zum reibungslosen Durchlaufen von [key, value]Paaren umfasst. Wie es in anderen Sprachen zum Beispiel Ruby möglich ist.

Ok hier ist ein Code:

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
  [Symbol.iterator]: function* () {
    for (const i of Object.keys(this)) {
      yield [i, this[i]];
    }
  }
};

for (const [k, v] of MyObject) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Alle Informationen dazu, wie Sie einen Iterator und Generator ausführen können, finden Sie auf der Entwickler-Mozilla-Seite.

Hoffe es hat jemandem geholfen.

BEARBEITEN:

ES2017 wird enthalten, Object.entrieswas das Iterieren über [key, value]Paare in Objekten noch einfacher macht. Es ist jetzt bekannt, dass es Teil eines Standards gemäß ts39 sein wird .

Ich denke, es ist Zeit, meine Antwort zu aktualisieren, damit sie noch frischer wird als jetzt.

const MyObject = {
  'a': 'Hello',
  'b': 'it\'s',
  'c': 'me',
  'd': 'you',
  'e': 'looking',
  'f': 'for',
};

for (const [k, v] of Object.entries(MyObject)) {
  console.log(`Here is key ${k} and here is value ${v}`);
}

Weitere Informationen zur Verwendung finden Sie auf der MDN- Seite

FieryCod
quelle
Das sieht für mich völlig überflüssig / unnötig aus. Würden Sie es jedem Objekt in Ihrem System hinzufügen? Ich dachte, der Sinn der Bereitstellung eines Iterators wäre, dass Sie "für (const [k, v] von myObject)" tun könnten. Es sieht aus wie zusätzlicher Code, der wenig zusätzlichen Wert bietet.
Dean Radcliffe
22
for(key in p) {
  alert( p[key] );
}

Hinweis: Sie können dies über Arrays tun, aber Sie werden auch über die lengthund andere Eigenschaften iterieren .

Richard Levasseur
quelle
4
Wenn Sie eine solche for-Schleife verwenden, keywird nur ein Indexwert angenommen, sodass nur 0, 1, 2 usw. angezeigt werden. Sie müssen auf p [key] zugreifen.
Bryan
1
Dies ist die langsamste Methode zur Array-Iteration in JavaScript. Sie können dies auf Ihrem Computer überprüfen - Beste Möglichkeit, über Arrays in JavaScript zu iterieren
Pencroff
5
@Pencroff: Das Problem ist, dass die Frage nicht über das Durchlaufen von Arrays geht ...;)
Sk8erPeter
Dies ist etwas, das ich beim Stackoverflow nicht verstehe. Richard gab die richtige Antwort und er war der erste, der diese Antwort gab, aber er bekam keine +1? @Bryan var p = {"p1":"q","p2":"w"}; for(key in p) { alert( key ); }knallt "p1" und "p2" in Warnungen, also was ist daran falsch ???
Sebastian
5
Ich denke, der Hauptunterschied ist die Qualität: Die anderen Antworten zeigen nicht nur, wie, sondern auch die Vorbehalte (z. B. der Prototyp) und wie mit diesen Vorbehalten umgegangen werden soll. IMHO, diese anderen Antworten sind besser als meine :).
Richard Levasseur
20

Nachdem ich alle Antworten hier durchgesehen habe, ist hasOwnProperty für meine eigene Verwendung nicht erforderlich, da mein json-Objekt sauber ist. Es macht wirklich keinen Sinn, zusätzliche Javascript-Verarbeitung hinzuzufügen. Das ist alles was ich benutze:

for (var key in p) {
    console.log(key + ' => ' + p[key]);
    // key is key
    // value is p[key]
}
Francis Lewis
quelle
18
Ob das JSON-Objekt sauber ist oder nicht, spielt keine Rolle. Wenn zu irgendeinem anderen Zeitpunkt ein Code eine Eigenschaft festlegt Object.prototype, wird diese von aufgelistet for..in. Wenn Sie sicher sind, dass Sie keine Bibliotheken verwenden, die dies tun, müssen Sie nicht aufrufen hasOwnProperty.
G-Wiz
4
Es kann völlig sauber sein, wenn es mitObject.create(null)
Juan Mendes
20

über einen Prototyp mit forEach (), der die Eigenschaften der Prototypenkette überspringen sollte :

Object.prototype.each = function(f) {
    var obj = this
    Object.keys(obj).forEach( function(key) { 
        f( key , obj[key] ) 
    });
}


//print all keys and values
var obj = {a:1,b:2,c:3}
obj.each(function(key,value) { console.log(key + " " + value) });
// a 1
// b 2
// c 3
Strider
quelle
2
Seien Sie vorsichtig mit dem Prototyp: obj = { print: 1, each: 2, word: 3 }produziert TypeError: number is not a function. Die Verwendung forEachzur Anpassung an die ähnliche ArrayFunktion kann das Risiko etwas verringern.
David Harkness
18

Es ist interessant, dass Menschen in diesen Antworten beide berührt Object.keys()und for...ofsie nie kombiniert haben:

var map = {well:'hello', there:'!'};
for (let key of Object.keys(map))
    console.log(key + ':' + map[key]);

Sie können nicht einfach for...ofein, Objectweil es kein Iterator ist, for...indexoder .forEach()das Object.keys()ist hässlich / ineffizient.
Ich bin froh, dass die meisten Leute davon Abstand nehmen for...in(mit oder ohne Überprüfung .hasOwnProperty()), da dies auch etwas chaotisch ist. Abgesehen von meiner obigen Antwort bin ich hier, um zu sagen ...


Sie können gewöhnliche Objektassoziationen iterieren lassen! Benimm dich wie Maps mit direkter Verwendung des ausgefallenen for...of
DEMO , das in Chrome und FF funktioniert (ich nehme nur ES6 an)

var ordinaryObject = {well:'hello', there:'!'};
for (let pair of ordinaryObject)
    //key:value
    console.log(pair[0] + ':' + pair[1]);

//or
for (let [key, value] of ordinaryObject)
    console.log(key + ':' + value);

Solange Sie meine Unterlegscheibe unten angeben:

//makes all objects iterable just like Maps!!! YAY
//iterates over Object.keys() (which already ignores prototype chain for us)
Object.prototype[Symbol.iterator] = function() {
    var keys = Object.keys(this)[Symbol.iterator]();
    var obj = this;
    var output;
    return {next:function() {
        if (!(output = keys.next()).done)
            output.value = [output.value, obj[output.value]];
        return output;
    }};
};

Ohne ein echtes Map-Objekt erstellen zu müssen, das nicht den schönen syntaktischen Zucker enthält.

var trueMap = new Map([['well', 'hello'], ['there', '!']]);
for (let pair of trueMap)
    console.log(pair[0] + ':' + pair[1]);

Wenn Sie mit diesem Shim die anderen Funktionen von Map nutzen möchten (ohne sie alle einzuschränken), aber dennoch die saubere Objektnotation verwenden möchten, da Objekte jetzt iterierbar sind, können Sie jetzt einfach eine Map daraus erstellen!

//shown in demo
var realMap = new Map({well:'hello', there:'!'});

Für diejenigen, die nicht gerne shimen oder sich prototypeim Allgemeinen damit anlegen, können Sie die Funktion stattdessen im Fenster ausführen und sie so etwas wie getObjIterator()damals nennen.

//no prototype manipulation
function getObjIterator(obj) {
    //create a dummy object instead of adding functionality to all objects
    var iterator = new Object();

    //give it what the shim does but as its own local property
    iterator[Symbol.iterator] = function() {
        var keys = Object.keys(obj)[Symbol.iterator]();
        var output;

        return {next:function() {
            if (!(output = keys.next()).done)
                output.value = [output.value, obj[output.value]];
            return output;
        }};
    };

    return iterator;
}

Jetzt können Sie es einfach als normale Funktion aufrufen, nichts anderes ist betroffen

var realMap = new Map(getObjIterator({well:'hello', there:'!'}))

oder

for (let pair of getObjIterator(ordinaryObject))

Es gibt keinen Grund, warum das nicht funktionieren würde.

Willkommen in der Zukunft.

Hashbrown
quelle
1
Fall in Punkt . Solange die Leute nach unten scrollen und es hilfreich finden, ist das alles, was zählt. Normalerweise versuche ich etwas zu tun, mag die Dinge, die ich online sehe, nicht, finde es heraus und komme dann zurück, um sie zu teilen. Es ist ein gutes Dokument, ich habe tatsächlich meine eigenen Antworten gefunden, bevor ich Dinge gegoogelt habe, die ich völlig vergessen habe!
Hashbrown
@HelpMeStackOverflowMyOnlyHope Persönlich mag ich es nicht, die Prototypen von Objekten zu ändern, die ich nicht selbst definiert habe.
Janus Troelsen
@ JanusTroelsen hast du überhaupt die ganze Antwort gelesen? 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;
Hashbrown
Beachten Sie, dass diese Technik bei einfachen Objekten nicht funktioniert, aber dennoch nützlich ist.
noɥʇʎԀʎzɐɹƆ
Es funktioniert für einfache Objekte, das ist buchstäblich der springende Punkt (ebenso wie die Variablennamen, ordinaryObjectum zu betonen, dass die Magie für diese Typen immer noch funktioniert). Haben Sie die Demos überprüft? Was funktioniert bei dir nicht, @ noɥʇʎԀʎzɐɹƆ? (PS Ihr SE-Profilbild ist Chef)
Hashbrown
13

Object.keys (obj): Array

Ruft alle Schlüssel mit Zeichenfolgenwerten aller aufzählbaren eigenen (nicht vererbten) Eigenschaften ab.

Sie erhalten also dieselbe Liste von Schlüsseln, die Sie beabsichtigen, indem Sie jeden Objektschlüssel mit hasOwnProperty testen. Sie benötigen diesen zusätzlichen Testvorgang nicht als und Object.keys( obj ).forEach(function( key ){})soll schneller sein. Lassen Sie es uns beweisen:

var uniqid = function(){
			var text = "",
					i = 0,
					possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
			for( ; i < 32; i++ ) {
					text += possible.charAt( Math.floor( Math.random() * possible.length ) );
			}
			return text;
		}, 
		CYCLES = 100000,
		obj = {}, 
		p1,
		p2,
		p3,
		key;

// Populate object with random properties
Array.apply( null, Array( CYCLES ) ).forEach(function(){
	obj[ uniqid() ] = new Date()
});

// Approach #1
p1 = performance.now();
Object.keys( obj ).forEach(function( key ){
	var waste = obj[ key ];
});

p2 = performance.now();
console.log( "Object.keys approach took " + (p2 - p1) + " milliseconds.");

// Approach #2
for( key in obj ) {
	if ( obj.hasOwnProperty( key ) ) {
		var waste = obj[ key ];
	}
}

p3 = performance.now();
console.log( "for...in/hasOwnProperty approach took " + (p3 - p2) + " milliseconds.");

In meinem Firefox habe ich folgende Ergebnisse

  • Der Object.keys-Ansatz dauerte 40,21101451665163 Millisekunden.
  • Für ... in / hasOwnProperty dauerte der Ansatz 98,26163508463651 Millisekunden.

PS. auf Chrome ist der Unterschied noch größer http://codepen.io/dsheiko/pen/JdrqXa

PS2: In ES6 (EcmaScript 2015) können Sie iterierbare Objekte besser iterieren:

let map = new Map().set('a', 1).set('b', 2);
for (let pair of map) {
    console.log(pair);
}

// OR 
let map = new Map([
    [false, 'no'],
    [true,  'yes'],
]);
map.forEach((value, key) => {
    console.log(key, value);
});

Dmitry Sheiko
quelle
Wenn Sie nicht die {} Notation of Map
loslassen möchten
13

Hier ist eine andere Methode zum Durchlaufen eines Objekts.

   var p = {
"p1": "value1",
"p2": "value2",
"p3": "value3"
};


Object.keys(p).forEach(key => { console.log(key, p[key]) })

Harter Patel
quelle
3
Dies ist ziemlich cool, aber für große Objekte ist die forMethode möglicherweise leistungsfähiger.
Rolf
13

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

for (var key in p) {
    if (p.hasOwnProperty(key)) {
        console.log(key + " = " + p[key]);
    }
}
<p>
  Output:<br>
  p1 = values1<br>
  p2 = values2<br>
  p3 = values3
</p>

ParaMeterz
quelle
12

Sie können auch Object.keys () verwenden und die Objektschlüssel wie unten durchlaufen, um den Wert zu erhalten:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).forEach((key)=> {
 console.log(key +' -> '+ p[key]);
});

Onera
quelle
Du hast meine Zeit gespart, danke
Swap-IOS-Android
Glücklich zu wissen :)
Onera
8

Nur JavaScript-Code ohne Abhängigkeiten:

var p = {"p1": "value1", "p2": "value2", "p3": "value3"};
keys = Object.keys(p);   // ["p1", "p2", "p3"]

for(i = 0; i < keys.length; i++){
  console.log(keys[i] + "=" + p[keys[i]]);   // p1=value1, p2=value2, p3=value3
}
mohamed-ibrahim
quelle
8

Die Object.keys()Methode gibt ein Array der eigenen aufzählbaren Eigenschaften eines bestimmten Objekts zurück. Lesen Sie hier mehr darüber

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3"
};

Object.keys(p).map((key)=> console.log(key + "->" + p[key]))

George Bailey
quelle
8

Performance

Heute 2020.03.06 teste ich ausgewählte Lösungen unter Chrome v80.0, Safari v13.0.5 und Firefox 73.0.1 unter MacOs High Sierra v10.13.6

Schlussfolgerungen

  • Lösungen basierend auf for-in (A, B) , sind für alle Browser für große und kleine Objekte schnell (oder am schnellsten)
  • überraschenderweise for-of (H) -Lösung auf Chrom für kleine und große Objekte schnell
  • Lösungen basierend auf explizitem Index i (J, K) basieren, sind in allen Browsern für kleine Objekte recht schnell (für Firefox auch schnell für große Objekte, in anderen Browsern jedoch mittelschnell).
  • Lösungen, die auf Iteratoren (D, E) basieren, sind am langsamsten und werden nicht empfohlen
  • Lösung C ist langsam für große Objekte und mittel-langsam für kleine Objekte

Geben Sie hier die Bildbeschreibung ein

Einzelheiten

Leistungstests wurden für durchgeführt

  • kleines Objekt - mit 3 Feldern - können Sie Tests auf Ihrem Computer durchführen HIER
  • 'großes' Objekt - mit 1000 Feldern - können Sie HIER einen Test auf Ihrem Computer durchführen

In den folgenden Ausschnitten werden verwendete Lösungen vorgestellt

Und hier sind Ergebnisse für kleine Objekte auf Chrom

Geben Sie hier die Bildbeschreibung ein

Kamil Kiełczewski
quelle
7

Sie können allen Objekten eine einfache forEach- Funktion hinzufügen , sodass Sie jedes Objekt automatisch durchlaufen können:

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        for (var key in this) {
            if (!this.hasOwnProperty(key)) {
                // skip loop if the property is from prototype
                continue;
            }
            var value = this[key];
            func(key, value);
        }
    },
    enumerable: false
});

Für diejenigen, die die " for ... in " -Methode nicht mögen :

Object.defineProperty(Object.prototype, 'forEach', {
    value: function (func) {
        var arr = Object.keys(this);
        for (var i = 0; i < arr.length; i++) {
            var key = arr[i];
            func(key, this[key]);
        }
    },
    enumerable: false
});

Jetzt können Sie einfach anrufen:

p.forEach (function(key, value){
    console.log ("Key: " + key);
    console.log ("Value: " + value);
});

Wenn Sie keine Konflikte mit anderen forEach-Methoden erhalten möchten, können Sie diese mit Ihrem eindeutigen Namen benennen.

Biber
quelle
3
Das Ändern der Prototypen von eingebauten Objekten (wie Object) wird im Allgemeinen als Anti-Pattern angesehen, da dies leicht zu Konflikten mit anderem Code führen kann. Wunde also nicht empfehlen, es so zu machen.
Moritz
6

Schleifen können bei Verwendung von reinem JavaScript sehr interessant sein. Es scheint, dass nur ECMA6 (New 2015 JavaScript Specification) die Schleifen unter Kontrolle gebracht hat. Während ich dies schreibe, haben leider sowohl Browser als auch die beliebte integrierte Entwicklungsumgebung (IDE) immer noch Probleme, die neuen Schnickschnack vollständig zu unterstützen.

Auf einen Blick sehen Sie hier, wie eine JavaScript-Objektschleife vor ECMA6 aussieht:

for (var key in object) {
  if (p.hasOwnProperty(key)) {
    var value = object[key];
    console.log(key); // This is the key;
    console.log(value); // This is the value;
  }
}

Ich weiß auch, dass dies bei dieser Frage nicht möglich ist, aber 2011 hat ECMAScript 5.1 die forEachMethode nur für Arrays hinzugefügt, die im Grunde eine neue verbesserte Methode zum Durchlaufen von Arrays geschaffen hat, während nicht iterierbare Objekte mit der alten ausführlichen und verwirrenden forSchleife belassen werden . Aber der seltsame Teil ist, dass diese neue forEachMethode nicht unterstütztbreak , was zu allen möglichen anderen Problemen führte.

Grundsätzlich gibt es 2011 keinen wirklich soliden Weg, um JavaScript zu wiederholen, außer dem, was viele beliebte Bibliotheken (jQuery, Underscore usw.) für eine Neuimplementierung beschlossen haben.

Ab 2015 haben wir jetzt eine bessere Möglichkeit, jeden Objekttyp (einschließlich Arrays und Strings) zu schleifen (und zu brechen). So sieht eine Schleife in JavaScript schließlich aus, wenn die Empfehlung zum Mainstream wird:

for (let [key, value] of Object.entries(object)) {
    console.log(key); // This is the key;
    console.log(value); // This is the value;
}

Beachten Sie, dass die meisten Browser den obigen Code ab dem 18. Juni 2016 nicht mehr unterstützen. Selbst in Chrome müssen Sie dieses spezielle Flag aktivieren, damit es funktioniert: chrome://flags/#enable-javascript-harmony

Bis dies zum neuen Standard wird, kann die alte Methode weiterhin verwendet werden, aber es gibt auch Alternativen in gängigen Bibliotheken oder sogar leichtgewichtige Alternativen für diejenigen, die keine dieser Bibliotheken verwenden.

Nicolas Bouvrette
quelle
Könnten Sie eine Geige dieser Arbeit liefern? Hier ist mein Versuch. jsfiddle.net/abalter/sceeb211
abalter
@abalter Entschuldigung, ich habe festgestellt, dass mein Code einen Tippfehler enthält. Ich habe es behoben und Ihre JsFiddle hier aktualisiert: jsfiddle.net/sceeb211/2
Nicolas Bouvrette
Ich bin in Chrom und bekomme Uncaught TypeError: Object.entries is not a function. Ist es noch nicht in Chrome implementiert?
Abalter
@abalter Es ist. Stellen Sie sicher, dass Sie über Chrome Version 51 verfügen und das Flag aktiviert haben, wie in meinen Kommentaren zu Bearbeitung und Jsfiddle erläutert. Sie können die Details hier überprüfen: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
Nicolas Bouvrette
Tut mir leid, dass ich das wegen der Flagge verpasst habe. Ich sehe, dass es noch keine vollständig implementierte Funktion ist.
Abalter
5

In ES6 haben wir bekannte Symbole, um einige zuvor interne Methoden verfügbar zu machen. Sie können damit definieren, wie Iteratoren für dieses Objekt funktionieren:

var p = {
    "p1": "value1",
    "p2": "value2",
    "p3": "value3",
    *[Symbol.iterator]() {
        yield *Object.keys(this);
    }
};

[...p] //["p1", "p2", "p3"]

Dies ergibt das gleiche Ergebnis wie die Verwendung von for ... in der es6-Schleife.

for(var key in p) {
    console.log(key);
}

Es ist jedoch wichtig zu wissen, über welche Funktionen Sie jetzt mit es6 verfügen!

Bamieh
quelle
1
Ein benutzerdefinierter Objektiterator ruft den integrierten Array-Iterator eines Arrays auf, das vom Object.keys()Speicher generiert und im Speicher zugewiesen wird ... Cool!
ooo
5

Ich würde dies tun, anstatt obj.hasOwnerPropertyin jeder for ... inSchleife zu überprüfen .

var obj = {a : 1};
for(var key in obj){
    //obj.hasOwnProperty(key) is not needed.
    console.log(key);
}
//then check if anybody has messed the native object. Put this code at the end of the page.
for(var key in Object){
    throw new Error("Please don't extend the native object");
}
Lewis
quelle
5

    var p =[{"username":"ordermanageadmin","user_id":"2","resource_id":"Magento_Sales::actions"},
{"username":"ordermanageadmin_1","user_id":"3","resource_id":"Magento_Sales::actions"}]
for(var value in p) {
    for (var key in value) {
        if (p.hasOwnProperty(key)) {
            console.log(key + " -> " + p[key]);
        }
    }
}

senthil
quelle
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]); } } }
Marek Bernád
5

Mit Hilfe eines for-ofaufObject.keys()

Mögen:

let object = {
   "key1": "value1"
   "key2": "value2"
   "key3": "value3"
};

for (var key of Object.keys(p)) {
   console.log(key + " : " + object[key])
}
Nicolas Cabanas
quelle
4

Wenn Sie auch über nicht aufzählbare Eigenschaften iterieren möchten , können Sie Object.getOwnPropertyNames(obj)ein Array aller Eigenschaften (aufzählbar oder nicht aufzählbar) zurückgeben, die direkt auf einem bestimmten Objekt gefunden wurden.

var obj = Object.create({}, {
  // non-enumerable property
  getFoo: {
    value: function() { return this.foo; },
    enumerable: false
  }
});

obj.foo = 1; // enumerable property

Object.getOwnPropertyNames(obj).forEach(function (name) {
  document.write(name + ': ' + obj[name] + '<br/>');
});

Dheeraj Vepakomma
quelle
2
Das ist fantastisch, danke, dass du diese Antwort gepostet hast. Ich musste ein ErrorObjekt überprüfen und konnte die Eigenschaften in einer Schleife oder einem _.forIn(err)Aufruf nicht erreichen. Mit Object.getOwnPropertyNames(err)konnte ich auf alle Teile zugreifen Error, die ich vorher nicht erreichen konnte. Vielen Dank!
Pierce
4

Wenn jemand arrayObjects mit der Bedingung durchlaufen muss :

var arrayObjects = [{"building":"A", "status":"good"},{"building":"B","status":"horrible"}];

for (var i=0; i< arrayObjects.length; i++) {
  console.log(arrayObjects[i]);
  
  for(key in arrayObjects[i]) {      
    
      if (key == "status" && arrayObjects[i][key] == "good") {
        
          console.log(key + "->" + arrayObjects[i][key]);
      }else{
          console.log("nothing found");
      }
   }
}

Tadas V.
quelle
4

In Anbetracht von ES6 möchte ich meinen eigenen Löffel Zucker hinzufügen und einen weiteren Ansatz zum Durchlaufen der Objekteigenschaften bereitstellen.

Da ein einfaches JS-Objekt nicht sofort iterierbar ist , können wir die for..ofSchleife nicht zum Durchlaufen des Inhalts verwenden. Aber niemand kann uns aufhalten , es iterierbar zu machen .

Lassen Sie uns bookObjekt haben.

let book = {
  title: "Amazing book",
  author: "Me",
  pages: 3
}

book[Symbol.iterator] = function(){

  let properties = Object.keys(this); // returns an array with property names
  let counter = 0;
  let isDone = false;

  let next = () => {
    if(counter >= properties.length){
      isDone = true;
    }
    return { done: isDone, value: this[properties[counter++]] }
  }

  return { next };
}

Da wir es geschafft haben, können wir es folgendermaßen verwenden:

for(let pValue of book){
  console.log(pValue);
}
------------------------
Amazing book
Me
3

Oder wenn Sie die Leistung von ES6- Generatoren kennen , können Sie den obigen Code sicherlich viel kürzer machen.

book[Symbol.iterator] = function *(){

  let properties = Object.keys(this);
  for (let p of properties){
    yield this[p];
  }

}

Sicher, Sie können ein solches Verhalten auf alle Objekte anwenden, indem Sie es Objectauf prototypeEbene iterierbar machen .

Object.prototype[Symbol.iterator] = function() {...}

Außerdem können Objekte, die dem iterierbaren Protokoll entsprechen, mit dem neuen ES2015-Feature- Spread- Operator verwendet werden, sodass Objekteigenschaftswerte als Array gelesen werden können.

let pValues = [...book];
console.log(pValues);
-------------------------
["Amazing book", "Me", 3]

Oder Sie können die Destrukturierungszuweisung verwenden :

let [title, , pages] = book; // notice that we can just skip unnecessary values
console.log(title);
console.log(pages);
------------------
Amazing book
3

Sie können JSFiddle mit dem gesamten Code auschecken , den ich oben angegeben habe.

Artyom Pranovich
quelle
Ich habe festgestellt, dass der Code die Werte generiert, jedoch ohne Schlüssel. Ist es möglich, die Werte mit Schlüsseln zu iterieren?
Pika
Ja, du kannst. Geben Sie einfach "yield [key, obj [key]]" zurück. von Ihrer Generatorfunktion und verwenden Sie es dann wie folgt "für (lassen Sie [Schlüssel, Wert] von {}) {}"
Artyom Pranovich
4

seit ES06 können Sie die Werte eines Objekts als Array mit abrufen

let arrValues = Object.values( yourObject) ;

Es gibt ein Array der Objektwerte zurück und extrahiert keine Werte aus Prototype !!

MDN DOCS Object.values ​​()

und für Schlüssel (hier schon vor mir beantwortet)

let arrKeys   = Object.keys(yourObject);
yehonatan yehezkel
quelle
In den Antworten wird nach einer Lösung gefragt, die sowohl Schlüssel als auch Werte zurückgibt.
Sean Lindo
4

Im neuesten ES-Skript können Sie Folgendes tun:

let p = {foo: "bar"};
for (let [key, value] of Object.entries(p)) {
  console.log(key, value);
}

Ankit
quelle