Wie iteriere ich über ein JavaScript-Objekt?


421

Ich habe ein Objekt in JavaScript:

{
    abc: '...',
    bca: '...',
    zzz: '...',
    xxx: '...',
    ccc: '...',
    // ...
}

Ich möchte eine forSchleife verwenden, um ihre Eigenschaften zu erhalten. Und ich möchte es in Teilen wiederholen (nicht alle Objekteigenschaften gleichzeitig).

Mit einem einfachen Array kann ich es mit einer Standardschleife machen for:

for (i = 0; i < 100; i++) { ... } // first part
for (i = 100; i < 300; i++) { ... } // second
for (i = 300; i < arr.length; i++) { ... } // last

Aber wie geht das mit Objekten?


22
Beachten Sie, dass Objekteigenschaften nicht in der richtigen Reihenfolge gespeichert werden. Wenn Sie ein Objekt durchlaufen, gibt es keine Garantie für die Reihenfolge, in der es angezeigt wird.
James Allardice

Antworten:


849

Verwenden Sie für die meisten Objekte for .. in:

for (let key in yourobject) {
  console.log(key, yourobject[key]);
}

Wenn Sie mit ES6 sowohl Schlüssel als auch Werte gleichzeitig benötigen, tun Sie dies

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

Um zu vermeiden, dass geerbte Eigenschaften protokolliert werden, überprüfen Sie dies mit hasOwnProperty :

for (let key in yourobject) {
   if (yourobject.hasOwnProperty(key)) {
      console.log(key, yourobject[key]);
   }
}

Sie müssen hasOwnPropertybeim Iterieren von Schlüsseln nicht überprüfen, ob Sie ein einfaches Objekt verwenden (zum Beispiel eines, mit dem Sie sich selbst erstellt haben {}).

In dieser MDN-Dokumentation wird allgemeiner erläutert, wie mit Objekten und ihren Eigenschaften umgegangen wird.

Wenn Sie dies "in Blöcken" tun möchten, extrahieren Sie am besten die Schlüssel in einem Array. Da die Bestellung nicht garantiert ist, ist dies der richtige Weg. In modernen Browsern können Sie verwenden

let keys = Object.keys(yourobject);

Um kompatibler zu sein, sollten Sie Folgendes tun:

 let keys = [];
 for (let key in yourobject) {      
     if (yourobject.hasOwnProperty(key)) keys.push(key);
 }

Dann können Sie sich auf Ihre Eigenschaften von Index iterieren: yourobject[keys[i]]:

for (let i=300; i < keys.length && i < 600; i++) { 
   console.log(keys[i], yourobject[keys[i]]);
}

3
OP möchte dies in Blöcken ausführen, nicht alle Schlüssel in einer einzigen Schleife.
Pawel

Ja. Nicht volles Objekt in einer Schleife.
Nkuhta

2
@Cerbrus Das OP weiß bereits, wie ein Array in Teilen iteriert wird. Die Verwendung keysdes angegebenen Codes sollte ausreichen.
Yoshi

2
@ Cerbrus Bitte vor dem Kommentieren lesen! Was ist in "Um kompatibler zu sein, tun Sie dies besser" nicht klar ?
Denys Séguret

2
@ am05mhz Wie gesagt, es ist bei den meisten Objekten nutzlos. Aber nicht für alle. Versuchen Sie dies: jsbin.com/hirivubuta/1/edit?js,console,output
Denys Séguret

61

Hier ist eine weitere Iterationslösung für moderne Browser:

Object.keys(obj)
  .filter((k, i) => i >= 100 && i < 300)
  .forEach(k => console.log(obj[k]));

Oder ohne Filterfunktion:

Object.keys(obj).forEach((k, i) => {
    if (i >= 100 && i < 300) {
        console.log(obj[k]);
    }
});

Sie müssen jedoch berücksichtigen, dass Eigenschaften im JavaScript-Objekt nicht sortiert sind, dh keine Reihenfolge haben.


Wenn ich die Schleife unterbreche, beginnt sie beim nächsten Mal am Anfang des Objekts, das ist nicht der richtige Weg.
Nkuhta

21

Mit Object.entriesdir machst du so etwas.

 // array like object with random key ordering
 const anObj = { 100: 'a', 2: 'b', 7: 'c' };
 console.log(Object.entries(anObj)); // [ ['2', 'b'],['7', 'c'],['100', 'a'] ]

Die Object.entries () -Methode gibt ein Array der eigenen aufzählbaren Eigenschaft eines bestimmten Objekts zurück [Schlüssel, Wert]

Sie können also über das Objekt iterieren keyund valuefür jedes Objekt haben und so etwas erhalten.

const anObj = { 100: 'a', 2: 'b', 7: 'c' };
Object.entries(anObj).map(obj => {
   const key   = obj[0];
   const value = obj[1];

   // do whatever you want with those values.
});

oder so

// Or, using array extras
Object.entries(obj).forEach(([key, value]) => {
  console.log(`${key} ${value}`); // "a 5", "b 7", "c 9"
});

Eine Referenz finden Sie in den MDN-Dokumenten für Objekteinträge


17

Mit den neuen ES6 / ES2015-Funktionen müssen Sie kein Objekt mehr verwenden, um über einen Hash zu iterieren. Sie können eine verwenden Karte verwenden . Javascript Maps halten die Schlüssel in der Einfügereihenfolge, was bedeutet, dass Sie sie durchlaufen können, ohne die hasOwnProperty überprüfen zu müssen, was immer wirklich ein Hack war.

Über eine Karte iterieren:

var myMap = new Map();
myMap.set(0, "zero");
myMap.set(1, "one");
for (var [key, value] of myMap) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

for (var key of myMap.keys()) {
  console.log(key);
}
// Will show 2 logs; first with "0" and second with "1"

for (var value of myMap.values()) {
  console.log(value);
}
// Will show 2 logs; first with "zero" and second with "one"

for (var [key, value] of myMap.entries()) {
  console.log(key + " = " + value);
}
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

oder verwenden Sie für jedes:

myMap.forEach(function(value, key) {
  console.log(key + " = " + value);
}, myMap)
// Will show 2 logs; first with "0 = zero" and second with "1 = one"

1
forEach ist der bevorzugte
pungggi

14

Wenn Sie den Schlüssel und den Wert beim Iterieren möchten , können Sie eine for ... of- Schleife mit Object.entries verwenden .

const myObj = {a: 1, b: 2}

for (let [key, value] of Object.entries(myObj)) {
    console.log(`key=${key} value=${value}`)
}

// output: 
// key=a value=1
// key=b value=2

7

Der einzig zuverlässige Weg, dies zu tun, besteht darin, Ihre Objektdaten in zwei Arrays zu speichern, einem der Schlüssel und einem für die Daten:

var keys = [];
var data = [];
for (var key in obj) {
    if (obj.hasOwnProperty(key)) {
        keys.push(key);
        data.push(obj[key]); // Not necessary, but cleaner, in my opinion. See the example below.
    }
}

Sie können dann wie gewohnt über die Arrays iterieren:

for(var i = 0; i < 100; i++){
    console.log(keys[i], data[i]);
    //or
    console.log(keys[i], obj[keys[i]]); // harder to read, I think.
}
for(var i = 100; i < 300; i++){
    console.log(keys[i], data[i]);
}

Ich benutze nicht Object.keys(obj), weil das IE 9+ ist.


3

-> wenn wir ein JavaScript-Objekt mit dem Schlüssel eines Array von Objekten durchlaufen und finden

Object.keys(Array).forEach(key => {

 console.log('key',key)

})

1

Wenn Sie das gesamte Objekt auf einmal iterieren möchten, können Sie die for inSchleife verwenden:

for (var i in obj) {
  ...
}

Aber wenn Sie das Objekt tatsächlich in Teile teilen möchten, können Sie dies nicht. Es gibt keine Garantie dafür, dass die Eigenschaften des Objekts in einer bestimmten Reihenfolge vorliegen. Daher kann ich mir zwei Lösungen vorstellen.

Zunächst müssen bereits gelesene Eigenschaften "entfernt" werden:

var i = 0;
for (var key in obj) {
    console.log(obj[key]);
    delete obj[key];
    if ( ++i > 300) break;
}

Eine andere Lösung, die ich mir vorstellen kann, ist die Verwendung von Array of Arrays anstelle des Objekts:

var obj = [['key1', 'value1'], ['key2', 'value2']];

Dann forfunktioniert die Standardschleife .


1

Ich habe mir endlich eine praktische Utility-Funktion mit einer einheitlichen Oberfläche ausgedacht, um Objekte, Strings, Arrays, TypedArrays, Maps, Sets (beliebige Iterables) zu iterieren.

const iterate = require('@a-z/iterate-it');
const obj = { a: 1, b: 2, c: 3 };

iterate(obj, (value, key) => console.log(key, value)); 
// a 1
// b 2
// c 3

https://github.com/alrik/iterate-javascript


1

Sie können versuchen, lodash zu verwenden. Eine moderne JavaScript-Dienstprogrammbibliothek, die Modularität, Leistung und Extras bietet, um Objekte schnell zu iterieren: -

var  users  =   {
    'fred':     { 
        'user':   'fred',
            'age':  40 
    },
    'pebbles':  { 
        'user':   'pebbles',
         'age':  1 
    }
}; 
_.mapValues(users,  function(o)  { 
    return  o.age; 
});
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
// The `_.property` iteratee shorthand.
console.log(_.mapValues(users,  'age')); // returns age property & value 
console.log(_.mapValues(users,  'user')); // returns user property & value 
console.log(_.mapValues(users)); // returns all objects 
// => { 'fred': 40, 'pebbles': 1 } (iteration order is not guaranteed)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash-compat/3.10.2/lodash.js"></script>


1

Für die Objektiteration verwenden wir normalerweise eine for..inSchleife. Diese Struktur durchläuft alle aufzählbaren Eigenschaften, einschließlich derjenigen, die über die prototypische Vererbung geerbt werden. Zum Beispiel:

let obj = {
  prop1: '1',
  prop2: '2'
}

for(let el in obj) {
  console.log(el);
  console.log(obj[el]);
}

Allerdings for..inwird Schleife über alle zählbare Elemente , und dies wird nicht in der Lage uns die Iteration in Stücke zu teilen. Um dies zu erreichen, können wir die eingebaute Object.keys()Funktion verwenden, um alle Schlüssel eines Objekts in einem Array abzurufen. Wir können dann die Iteration in mehrere for-Schleifen aufteilen und über das Schlüsselarray auf die Eigenschaften zugreifen. Zum Beispiel:

let obj = {
  prop1: '1',
  prop2: '2',
  prop3: '3',
  prop4: '4',
};

const keys = Object.keys(obj);
console.log(keys);


for (let i = 0; i < 2; i++) {
  console.log(obj[keys[i]]);
}


for (let i = 2; i < 4; i++) {
  console.log(obj[keys[i]]);
}


0
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);

1
Nicht wirklich. Dies impliziert, dass Objects in Ordnung sind. Sie sind nicht. If you can make sense of the sentence it workedfunktioniert nur aufgrund von Implementierungsdetails. Es ist nicht garantiert, dass es überhaupt funktioniert. Außerdem sollten Sie Ihre Funktionen und Variablen nicht mit TitleCase versehen. Das ist für classes.
Florian Wendelborn

0

Wirklich eine PITA, dies ist nicht Teil von Standard-Javascript.

/**
 * Iterates the keys and values of an object.  Object.keys is used to extract the keys.
 * @param object The object to iterate
 * @param fn (value,key)=>{}
 */
function objectForEach(object, fn) {
    Object.keys(object).forEach(key => {
        fn(object[key],key, object)
    })
}

Hinweis: Ich habe die Rückrufparameter auf (Wert, Schlüssel) umgestellt und ein drittes Objekt hinzugefügt, um die API mit anderen APIs konsistent zu machen.

Verwenden Sie es so

const o = {a:1, b:true};
objectForEach(o, (value, key, obj)=>{
    // do something
});

1
nur für Ihre Aussage im ersten Satz gestimmt. Auch wenn es besser wäre, wenn der Wert der erste Parameter, der zweite Index- oder Schlüsselparameter und der dritte Parameter des Objekts wäre, um es dem Array forEach () ähnlicher zu machen. Ich würde empfehlen, lodash zu empfehlen.
sagt, ich bin richtig

Ich mag die Idee der (Wert-, Schlüssel-) Reihenfolge. So macht es auch eine Bibliothek wie Vue. Da das Objekt der Kontext ist, glaubt es jedoch, dass es als erster Parameter gehört. Das ist ziemlich Standard für die funktionale Programmierung.
Steven Spungin

Ich würde hier zustimmen, wenn ECMA-262 ein Array nicht als ein Objekt mit forEach (), map (), redu (), filter () definieren würde, die alle Rückrufe entgegennehmen, die die Reihenfolge [value, index, array] erhalten. . Ein Objekt in JS kann als eine weitere Sammlung verstanden werden. und dann werden diese Methoden in ihren Parametern [Wert, Schlüssel | Index, Kontext] vereinheitlicht (dies ist, was lodash und Unterstrich tun). Meiner Meinung nach ist dieses "Unified Collection" -Protokoll nur stärker. Das Objekt ist auch nicht der Kontext: Sie können thisfür den Rückruf festlegen , was Sie möchten, da der Rückruf einen eigenen Kontext hat.
sagt, ich bin richtig

Vielleicht hätte ich stattdessen den Arbeitsempfänger verwenden sollen. Jedenfalls immer noch eine PITA; Ich würde die Parameter in beliebiger Reihenfolge begrüßen.
Steven Spungin

Oh, ich sehe, dass wir uns vielleicht missverstanden haben. Ich habe immer die Rückrufparameter und ihre Reihenfolge kommentiert, nicht die eigentliche objectForEachFunktion. Entschuldigung, wenn das verwirrend war.
sagt, ich bin richtig

0

Ja. Sie können ein Objekt mit der for-Schleife durchlaufen. Hier ist ein Beispiel

var myObj = {
    abc: 'ABC',
    bca: 'BCA',
    zzz: 'ZZZ',
    xxx: 'XXX',
    ccc: 'CCC',
}

var k = Object.keys (myObj);
for (var i = 0; i < k.length; i++) {
    console.log (k[i] + ": " + myObj[k[i]]);
}

HINWEIS: Das oben erwähnte Beispiel funktioniert nur in IE9 +. Siehe Objec.keys Browserunterstützung hier .


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.