Préliminaires
JavaScript ne possède qu'un seul type de données qui peut contenir plusieurs valeurs : Objet . Un site Array est une forme particulière d'objet.
(Plaine) Les objets ont la forme
{key: value, key: value, ...}
Les tableaux ont la forme
[value, value, ...]
Les tableaux et les objets présentent tous deux une fonction key -> value
structure. Les clés d'un tableau doivent être numériques, tandis que toute chaîne de caractères peut être utilisée comme clé dans les objets. Les paires clé-valeur sont également appelées "propriétés" .
On peut accéder aux propriétés soit en utilisant notation par points
const value = obj.someProperty;
ou notation entre crochets si le nom de la propriété n'est pas un nom JavaScript valide. nom de l'identifiant [spec] ou 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];
C'est pourquoi on ne peut accéder aux éléments d'un tableau qu'en utilisant la notation entre parenthèses :
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, il faut d'abord les convertir en types de données JavaScript, c'est-à-dire en tableaux et en objets (la façon de travailler avec ces derniers vient d'être expliquée). La façon d'analyser JSON est expliquée dans la question suivante Analyser JSON en JavaScript ? .
Matériel de lecture supplémentaire
La manière d'accéder aux tableaux et aux objets est une connaissance fondamentale de JavaScript et il est donc conseillé de lire le manuel Guide MDN du JavaScript 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. On peut accéder à de telles structures 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 voulions accéder au name
du deuxième élément.
Voici comment procéder, étape par étape :
Comme on peut le voir data
est un objet, nous pouvons donc accéder à ses propriétés en utilisant la notation point. Le site items
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 parenthèses :
data.items[1]
Cette valeur est un objet et nous utilisons à nouveau la notation point pour accéder à l'objet name
propriété. Donc on finit par obtenir :
const item_name = data.items[1].name;
Nous aurions également pu utiliser la notation par points pour toutes les 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 n'obtiens que undefined
de retour ?
La plupart du temps, lorsque vous obtenez undefined
l'objet/le tableau n'a tout simplement pas de propriété portant ce nom.
const foo = {bar: {baz: 42}};
console.log(foo.baz); // undefined
Utilisez console.log
ou console.dir
et inspecter la structure de l'objet / du tableau. La propriété à laquelle vous essayez d'accéder peut être en fait définie sur un objet / tableau imbriqué.
console.log(foo.bar.baz); // 42
Que faire si les noms des propriétés sont dynamiques et que je ne les connais pas à l'avance ?
Si les noms des propriétés 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 fonction for...in
[MDN] pour les objets et la for
[MDN] boucle pour les tableaux afin d'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 les objet comme ça :
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
}
En fonction de l'origine de l'objet (et de ce que vous voulez faire), il se peut que vous deviez tester à chaque itération si la propriété est réellement une propriété de l'objet, ou si c'est une propriété héritée. Vous pouvez le faire avec Object#hasOwnProperty
[MDN] .
Comme alternative à for...in
avec 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 itérer sur tous les éléments de la data.items
tableau nous utilisons un 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 des tableaux, mais il y a des raisons pour lesquelles cela devrait être évité : Pourquoi la méthode "for(var item in list)" avec des tableaux est-elle considérée comme une mauvaise pratique en JavaScript ? .
Avec la prise en charge croissante de l'ECMAScript 5 par les navigateurs, 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 l'option for...of
[MDN] qui fonctionne non seulement pour les tableaux, mais aussi pour n'importe quelle itérable :
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 je ne connais pas la "profondeur" de la structure de données ?
Outre les clés inconnues, la "profondeur" de la structure de données (c'est-à-dire le nombre d'objets imbriqués) 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 de données exacte.
Mais si la structure de données contient des motifs répétitifs, par exemple la représentation d'un arbre binaire, la solution consiste généralement à récursivement [Wikipedia] accéder à chaque niveau de la structure de données.
Voici un exemple pour obtenir le premier nœud de 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);
Une manière plus générique d'accéder à une structure de données imbriquée dont les clés et la profondeur sont inconnues consiste à tester le type de la valeur et à agir en conséquence.
Voici un exemple qui ajoute toutes les valeurs primitives d'une structure de données imbriquée dans un tableau (en supposant qu'elle ne contient pas de fonctions). 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
Comme 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] aidez-nous à le faire. Par exemple (sortie de la console Chrome) :
> console.log(data.items)
[ Object, Object ]
Nous voyons ici que data.items
est 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 développé, nous voyons qu'il a trois propriétés, id
, name
et __proto__
. Cette dernière est une propriété interne utilisée pour la chaîne de prototypes de l'objet. La chaîne de prototypes et l'héritage sont hors de portée de cette réponse, cependant.
28 votes
@Marcel : Il faut le lire comme suit : "J'ai une structure de données imbriquées ou JSON, comment puis-je accéder à une valeur spécifique ?". I connaissent la différence, mais beaucoup de gens ne la connaissent pas et peuvent chercher "JSON" plutôt que "objet". De nombreuses questions sont en fait du type "comment puis-je accéder à X dans ce JSON". Le seul endroit où je mentionne JSON dans ma réponse est lorsque j'explique ce que c'est. Si vous avez une suggestion pour mieux communiquer, je suis tout ouïe.
0 votes
Duplicata possible de Recherche JSON en JavaScript
0 votes
Cette réponse m'a aidé à résoudre le problème de l'accès aux objets imbriqués de façon très agréable et claire : stackoverflow.com/questions/6491463/ Permet d'écrire par exemple : someObject.access("firstPart[2].someOtherPart.myId")