Préliminaires
JavaScript n'a qu'un seul type de données qui peut contenir plusieurs valeurs: Objet . Un tableau est une forme spéciale d'objet.
(Ordinaire) Les objets ont la forme
{key: value, key: value, ...}
Les tableaux ont la forme
[value, value, ...]
Les tableaux et les objets exposent une key -> value
structure. Les clés d'un tableau doivent être numériques, tandis que n'importe quelle chaîne peut être utilisée comme clé dans des objets. Les paires clé-valeur sont également appelées "propriétés" .
Les propriétés sont accessibles soit en utilisant la notation par points
const value = obj.someProperty;
ou la notation entre crochets , si le nom de la propriété ne serait pas un nom d'identifiant JavaScript valide [spéc] , ou si le nom est la valeur d'une variable:
// 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];
Pour cette raison, les éléments du tableau ne sont accessibles qu'en utilisant la notation entre crochets:
const value = arr[5]; // arr.5 would be a syntax error
// property name / index as variable
const x = 5;
const value = arr[x];
Attendez ... et JSON?
JSON est une représentation textuelle des données, tout comme XML, YAML, CSV et autres. Pour travailler avec de telles données, elles doivent d'abord être converties en types de données JavaScript, c'est-à-dire des tableaux et des objets (et comment travailler avec ceux-ci vient d'être expliqué). Comment analyser JSON est expliqué dans la question Analyser JSON en JavaScript? .
Autres lectures
Comment accéder aux tableaux et aux objets est une connaissance fondamentale de JavaScript et il est donc conseillé de lire le guide JavaScript MDN , en particulier les sections
Accès aux structures de données imbriquées
Une structure de données imbriquée est un tableau ou un objet qui fait référence à d'autres tableaux ou objets, c'est-à-dire que ses valeurs sont des tableaux ou des objets. De telles structures sont accessibles en appliquant consécutivement la notation par points ou par crochets.
Voici un exemple:
const data = {
code: 42,
items: [{
id: 1,
name: 'foo'
}, {
id: 2,
name: 'bar'
}]
};
Supposons que nous voulons accéder name
au deuxième élément.
Voici comment nous pouvons le faire étape par étape:
Comme nous pouvons le voir data
est un objet, donc nous pouvons accéder à ses propriétés en utilisant la notation par points. La items
propriété est accessible comme suit:
data.items
La valeur est un tableau, pour accéder à son deuxième élément, nous devons utiliser la notation entre crochets:
data.items[1]
Cette valeur est un objet et nous utilisons à nouveau la notation par points pour accéder à la name
propriété. Nous obtenons donc finalement:
const item_name = data.items[1].name;
Alternativement, nous aurions pu utiliser la notation entre crochets pour l'une des propriétés, surtout si le nom contenait des caractères qui l'auraient rendu invalide pour l'utilisation de la notation par points:
const item_name = data['items'][1]['name'];
J'essaie d'accéder à une propriété mais je ne undefined
reviens que?
La plupart du temps, lorsque vous obtenez undefined
, l'objet / tableau n'a tout simplement pas de propriété avec ce nom.
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
Utilisez console.log
ou console.dir
et inspectez la structure de l'objet / du tableau. La propriété à laquelle vous essayez d'accéder peut être réellement définie sur un objet / tableau imbriqué.
console.log(foo.bar.baz); // 42
Que faire si les noms de propriété sont dynamiques et que je ne les connais pas au préalable?
Si les noms de propriété sont inconnus ou si nous voulons accéder à toutes les propriétés d'un objet / éléments d'un tableau, nous pouvons utiliser la boucle for...in
[MDN] pour les objets et la boucle for
[MDN] pour les tableaux pour itérer sur toutes les propriétés / éléments.
Objets
Pour itérer sur toutes les propriétés de data
, nous pouvons itérer sur l' objet comme ceci:
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
}
Selon d'où vient l'objet (et ce que vous voulez faire), vous devrez peut-être tester à chaque itération si la propriété est vraiment une propriété de l'objet ou une propriété héritée. Vous pouvez le faire avec Object#hasOwnProperty
[MDN] .
Comme alternative à for...in
with hasOwnProperty
, vous pouvez utiliser Object.keys
[MDN] pour obtenir un tableau de noms de propriétés :
Object.keys(data).forEach(function(prop) {
// `prop` is the property name
// `data[prop]` is the property value
});
Tableaux
Pour parcourir tous les éléments du data.items
tableau , nous utilisons une for
boucle:
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`.
}
On pourrait également utiliser for...in
pour itérer sur les tableaux, mais il y a des raisons pour lesquelles cela devrait être évité: Pourquoi est-ce que 'pour (élément var dans la liste)' avec des tableaux est considéré comme une mauvaise pratique en JavaScript? .
Avec la prise en charge croissante des navigateurs d'ECMAScript 5, la méthode de tableau forEach
[MDN] devient également une alternative intéressante:
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)
});
Dans les environnements prenant en charge ES2015 (ES6), vous pouvez également utiliser la boucle [MDN] , qui fonctionne non seulement pour les tableaux, mais pour tout élément itérable :for...of
for (const item of data.items) {
// `item` is the array element, **not** the index
}
Dans chaque itération, for...of
nous donne directement l'élément suivant de l'itérable, il n'y a pas d '"index" à accéder ou à utiliser.
Et si la "profondeur" de la structure de données m'est inconnue?
En plus des clés inconnues, la "profondeur" de la structure de données (c'est-à-dire le nombre d'objets imbriqués) qu'elle possède peut également être inconnue. La façon d'accéder aux propriétés profondément imbriquées dépend généralement de la structure exacte des données.
Mais si la structure de données contient des motifs répétitifs, par exemple la représentation d'un arbre binaire, la solution comprend généralement l' accès récursif [Wikipedia] à chaque niveau de la structure de données.
Voici un exemple pour obtenir le premier nœud feuille d'un arbre binaire:
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);
Un moyen plus générique d'accéder à une structure de données imbriquée avec des clés et une profondeur inconnues consiste à tester le type de la valeur et à agir en conséquence.
Voici un exemple qui ajoute toutes les valeurs primitives à l'intérieur d'une structure de données imbriquée dans un tableau (en supposant qu'elle ne contient aucune fonction). Si nous rencontrons un objet (ou un tableau), nous appelons simplement à toArray
nouveau sur cette valeur (appel récursif).
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));
Aides
Étant donné que la structure d'un objet ou d'un tableau complexe n'est pas nécessairement évidente, nous pouvons inspecter la valeur à chaque étape pour décider comment aller plus loin. console.log
[MDN] et console.dir
[MDN] nous aident à le faire. Par exemple (sortie de la console Chrome):
> console.log(data.items)
[ Object, Object ]
Ici, nous voyons que c'est data.items
un tableau avec deux éléments qui sont tous deux des objets. Dans la console Chrome, les objets peuvent même être développés et inspectés immédiatement.
> console.log(data.items[1])
Object
id: 2
name: "bar"
__proto__: Object
Cela nous dit que data.items[1]
est un objet, et après l' avoir étendu , nous voyons qu'il a trois propriétés, id
, name
et __proto__
. Ce dernier est une propriété interne utilisée pour la chaîne prototype de l'objet. La chaîne de prototype et l'héritage sont cependant hors de portée pour cette réponse.