Vorbereitungen
JavaScript hat nur einen Datentyp, der mehrere Werte enthalten kann: Objekt . Ein Array ist eine spezielle Objektform.
(Einfache) Objekte haben die Form
{key: value, key: value, ...}
Arrays haben die Form
[value, value, ...]
Sowohl Arrays als auch Objekte legen eine key -> value
Struktur frei. Schlüssel in einem Array müssen numerisch sein, während jede Zeichenfolge als Schlüssel in Objekten verwendet werden kann. Die Schlüssel-Wert-Paare werden auch als "Eigenschaften" bezeichnet. .
Auf Eigenschaften kann entweder mit Punktnotation zugegriffen werden
const value = obj.someProperty;
oder Klammernotation , wenn der Eigenschaftsname kein gültiger JavaScript- Bezeichnername [spec] wäre oder der Name der Wert einer Variablen ist:
// the space is not a valid character in identifier names
const value = obj["some Property"];
// property name as variable
const name = "some Property";
const value = obj[name];
Aus diesem Grund kann auf Array-Elemente nur in Klammernotation zugegriffen werden:
const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];
Warten Sie ... was ist mit JSON?
JSON ist eine Textdarstellung von Daten, genau wie XML, YAML, CSV und andere. Um mit solchen Daten arbeiten zu können, müssen sie zuerst in JavaScript-Datentypen, dh Arrays und Objekte, konvertiert werden (und wie mit diesen Daten gearbeitet wird, wurde gerade erklärt). Wie JSON analysiert wird, wird in der Frage JSON in JavaScript analysieren erläutert . .
Weiterführendes Lesematerial
Der Zugriff auf Arrays und Objekte ist ein grundlegendes JavaScript-Wissen. Daher ist es ratsam, das MDN-JavaScript-Handbuch zu lesen , insbesondere die Abschnitte
Zugriff auf verschachtelte Datenstrukturen
Eine verschachtelte Datenstruktur ist ein Array oder Objekt, das sich auf andere Arrays oder Objekte bezieht, dh ihre Werte sind Arrays oder Objekte. Auf solche Strukturen kann durch aufeinanderfolgendes Anwenden der Punkt- oder Klammernotation zugegriffen werden.
Hier ist ein Beispiel:
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
Nehmen wir an, wir wollen auf die zugreifen name
das zweite Element .
So können wir es Schritt für Schritt machen:
Wie wir sehen können, data
handelt es sich um ein Objekt, daher können wir mithilfe der Punktnotation auf seine Eigenschaften zugreifen. Auf die items
Unterkunft wird wie folgt zugegriffen:
data.items
Der Wert ist ein Array. Um auf sein zweites Element zuzugreifen, müssen wir die Klammernotation verwenden:
data.items[1]
Dieser Wert ist ein Objekt und wir verwenden erneut die Punktnotation, um auf die name
Eigenschaft zuzugreifen . So bekommen wir schließlich:
const item_name = data.items[1].name;
Alternativ hätten wir für jede der Eigenschaften die Klammernotation verwenden können, insbesondere wenn der Name Zeichen enthielt, die ihn für die Verwendung der Punktnotation ungültig gemacht hätten:
const item_name = data['items'][1]['name'];
Ich versuche, auf eine Immobilie zuzugreifen, bekomme aber nur undefined
zurück?
Meistens undefined
hat das Objekt / Array beim Abrufen einfach keine Eigenschaft mit diesem Namen.
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
Verwenden Sie console.log
oder console.dir
und überprüfen Sie die Struktur des Objekts / Arrays. Die Eigenschaft, auf die Sie zugreifen möchten, ist möglicherweise tatsächlich für ein verschachteltes Objekt / Array definiert.
console.log(foo.bar.baz); // 42
Was ist, wenn die Eigenschaftsnamen dynamisch sind und ich sie vorher nicht kenne?
Wenn die Eigenschaftsnamen unbekannt sind oder wir auf alle Eigenschaften eines Objekts / von Elementen eines Arrays zugreifen möchten, können wir die for...in
[MDN] -Schleife für Objekte und die for
[MDN] -Schleife für Arrays verwenden, um alle Eigenschaften / Elemente zu durchlaufen.
Objekte
Um alle Eigenschaften von zu durchlaufen data
, können wir das Objekt folgendermaßen durchlaufen :
for (const prop in data) {
// `prop` contains the name of each property, i.e. `'code'` or `'items'`
// consequently, `data[prop]` refers to the value of each property, i.e.
// either `42` or the array
}
Abhängig davon, woher das Objekt stammt (und was Sie tun möchten), müssen Sie möglicherweise in jeder Iteration testen, ob die Eigenschaft wirklich eine Eigenschaft des Objekts oder eine geerbte Eigenschaft ist. Sie können dies mit Object#hasOwnProperty
[MDN] tun .
Alternativ zu for...in
with hasOwnProperty
können Sie Object.keys
[MDN] verwenden , um ein Array von Eigenschaftsnamen abzurufen :
Object.keys(data).forEach(function(prop) {
// `prop` is the property name
// `data[prop]` is the property value
});
Arrays
Um alle Elemente des data.items
Arrays zu durchlaufen , verwenden wir eine for
Schleife:
for(let i = 0, l = data.items.length; i < l; i++) {
// `i` will take on the values `0`, `1`, `2`,..., i.e. in each iteration
// we can access the next element in the array with `data.items[i]`, example:
//
// var obj = data.items[i];
//
// Since each element is an object (in our example),
// we can now access the objects properties with `obj.id` and `obj.name`.
// We could also use `data.items[i].id`.
}
Man könnte auch verwenden for...in
, um über Arrays zu iterieren, aber es gibt Gründe, warum dies vermieden werden sollte: Warum ist 'for (var item in list)' bei Arrays, die in JavaScript als schlechte Praxis angesehen werden? .
Mit der zunehmenden Browserunterstützung von ECMAScript 5 wird auch die Array-Methode forEach
[MDN] zu einer interessanten Alternative:
data.items.forEach(function(value, index, array) {
// The callback is executed for each element in the array.
// `value` is the element itself (equivalent to `array[index]`)
// `index` will be the index of the element in the array
// `array` is a reference to the array itself (i.e. `data.items` in this case)
});
In Umgebungen, die ES2015 (ES6) unterstützen, können Sie auch die [MDN] -Schleife verwenden, die nicht nur für Arrays, sondern für alle iterierbaren Elemente funktioniert :for...of
for (const item of data.items) {
// `item` is the array element, **not** the index
}
In jeder Iteration for...of
gibt uns direkt das nächste Element der Iterable, es gibt keinen "Index", auf den zugegriffen oder der verwendet werden kann.
Was ist, wenn mir die "Tiefe" der Datenstruktur unbekannt ist?
Zusätzlich zu unbekannten Schlüsseln ist möglicherweise auch die "Tiefe" der Datenstruktur (dh wie viele verschachtelte Objekte) unbekannt. Wie auf tief verschachtelte Eigenschaften zugegriffen wird, hängt normalerweise von der genauen Datenstruktur ab.
Wenn die Datenstruktur jedoch sich wiederholende Muster enthält, z. B. die Darstellung eines Binärbaums, umfasst die Lösung normalerweise den rekursiven Zugriff [Wikipedia] auf jede Ebene der Datenstruktur.
Hier ist ein Beispiel, um den ersten Blattknoten eines Binärbaums zu erhalten:
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild); // <- recursive call
}
else if (node.rightChild) {
return getLeaf(node.rightChild); // <- recursive call
}
else { // node must be a leaf node
return node;
}
}
const first_leaf = getLeaf(root);
const root = {
leftChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 42
},
rightChild: {
leftChild: null,
rightChild: null,
data: 5
}
},
rightChild: {
leftChild: {
leftChild: null,
rightChild: null,
data: 6
},
rightChild: {
leftChild: null,
rightChild: null,
data: 7
}
}
};
function getLeaf(node) {
if (node.leftChild) {
return getLeaf(node.leftChild);
} else if (node.rightChild) {
return getLeaf(node.rightChild);
} else { // node must be a leaf node
return node;
}
}
console.log(getLeaf(root).data);
Eine allgemeinere Möglichkeit, auf eine verschachtelte Datenstruktur mit unbekannten Schlüsseln und unbekannter Tiefe zuzugreifen, besteht darin, den Typ des Werts zu testen und entsprechend zu handeln.
Hier ist ein Beispiel, das alle primitiven Werte innerhalb einer verschachtelten Datenstruktur zu einem Array hinzufügt (vorausgesetzt, es enthält keine Funktionen). Wenn wir auf ein Objekt (oder Array) stoßen, rufen wir toArray
diesen Wert einfach erneut auf (rekursiver Aufruf).
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value)); // <- recursive call
}
else {
result.push(value);
}
}
return result;
}
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
function toArray(obj) {
const result = [];
for (const prop in obj) {
const value = obj[prop];
if (typeof value === 'object') {
result.push(toArray(value));
} else {
result.push(value);
}
}
return result;
}
console.log(toArray(data));
Helfer
Da die Struktur eines komplexen Objekts oder Arrays nicht unbedingt offensichtlich ist, können wir den Wert bei jedem Schritt überprüfen, um zu entscheiden, wie Sie sich weiter bewegen möchten. console.log
[MDN] und console.dir
[MDN] helfen uns dabei. Zum Beispiel (Ausgabe der Chrome-Konsole):
> console.log(data.items)
[ Object, Object ]
Hier sehen wir, dass dies data.items
ein Array mit zwei Elementen ist, die beide Objekte sind. In der Chrome-Konsole können die Objekte sogar sofort erweitert und überprüft werden.
> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object
Dies sagt uns, dass data.items[1]
es sich um ein Objekt handelt, und nachdem wir es erweitert haben, sehen wir, dass es drei Eigenschaften hat id
, name
und __proto__
. Letzteres ist eine interne Eigenschaft, die für die Prototypkette des Objekts verwendet wird. Die Prototypkette und die Vererbung sind für diese Antwort jedoch nicht zulässig.