Comme nous le savons du chapitre Les types de donnĂ©es, il existe huit types de donnĂ©es dans le langage JavaScript. Sept dâentre elles sont appelĂ©es âprimitivesâ, car leurs valeurs ne contiennent quâune seule chose (que ce soit une chaĂźne, un nombre ou autre).
En revanche, les objets sont utilisĂ©s pour stocker des collections de donnĂ©es variĂ©es et dâentitĂ©s plus complexes. En JavaScript, les objets pĂ©nĂštrent dans presque tous les aspects du langage. Nous devons donc dâabord les comprendre avant dâaller plus loin.
Un objet peut ĂȘtre créé avec des accolades {âŠ}, avec une liste optionnelle de propriĂ©tĂ©s. Une propriĂ©tĂ© est une paire âclĂ©: valeurâ, dans laquelle la clĂ© (key) est une chaĂźne de caractĂšres (Ă©galement appelĂ©e ânom de la propriĂ©tĂ©â), et la valeur (value) peut ĂȘtre nâimporte quoi.
Nous pouvons imaginer un objet comme une armoire avec des fichiers signĂ©s. Chaque donnĂ©e est stockĂ©e dans son fichier par la clĂ©. Il est facile de trouver un fichier par son nom ou dâajouter/supprimer un fichier.
Un objet vide (âarmoire videâ) peut ĂȘtre créé en utilisant lâune des deux syntaxes suivantes :
let user = new Object(); // syntaxe "constructeur d'objet"
let user = {}; // syntaxe "littéral objet"
Habituellement, les accolades {...} sont utilisĂ©es. Cette dĂ©claration sâappelle un littĂ©ral objet (object literal).
Littéraux et propriétés
Nous pouvons immĂ©diatement inclure certaines propriĂ©tĂ©s dans {...} sous forme de paires âclĂ©: valeurâ :
let user = { // un objet
name: "John", // par clé "nom" valeur de stockage "John"
age: 30 // par clé "age" valeur de stockage 30
};
Une propriĂ©tĂ© a une clĂ© (Ă©galement appelĂ©e ânomâ ou âidentifiantâ) avant les deux points ":" et une valeur Ă sa droite.
Dans lâobjet user, il y a deux propriĂ©tĂ©s :
- La premiÚre propriété porte le nom
"name"et la valeur"John". - La seconde a le nom
"age"et la valeur30.
Lâobjet user rĂ©sultant peut ĂȘtre imaginĂ© comme une armoire avec deux fichiers signĂ©s intitulĂ©s ânomâ et âĂągeâ.
Nous pouvons ajouter, supprimer et lire des fichiers Ă tout moment.
Les valeurs de propriĂ©tĂ© sont accessibles Ă lâaide de la notation par points :
// récupÚre les valeurs de propriété de l'objet :
alert( user.name ); // John
alert( user.age ); // 30
La valeur peut ĂȘtre de tout type. Ajoutons un boolĂ©en :
user.isAdmin = true;
Pour supprimer une propriĂ©tĂ©, nous pouvons utiliser lâopĂ©rateur delete :
delete user.age;
Nous pouvons Ă©galement utiliser des noms de propriĂ©tĂ© multi-mots, mais ils doivent ensuite ĂȘtre entourĂ©s de quotes :
let user = {
name: "John",
age: 30,
"likes birds": true // le nom de la propriĂ©tĂ© multi-mots doit ĂȘtre entourĂ©e de quotes
};
La derniÚre propriété de la liste peut se terminer par une virgule :
let user = {
name: "John",
age: 30,
}
Cela sâappelle une virgule âtrailingâ ou âhangingâ. Elle facilite lâajout/suppression/dĂ©placement des propriĂ©tĂ©s, car toutes les lignes se ressemblent.
Crochets
Pour les propriĂ©tĂ©s multi-mots, lâaccĂšs par points ne fonctionne pas :
// cela donnerait une erreur de syntaxe
user.likes birds = true
JavaScript ne comprend pas cela. Il pense que nous adressons user.likes, ensuite il donne une erreur de syntaxe lorsquâil rencontre des birds inattendus.
Le point nĂ©cessite que la clĂ© soit un identificateur de variable valide. Cela implique quâelle ne contient aucun espace, ne commence pas par un chiffre et nâinclut pas de caractĂšres spĂ©ciaux ($ et _ sont autorisĂ©s).
Il existe une autre ânotation entre crochetsâ qui fonctionne avec nâimporte quelle chaĂźne :
let user = {};
// set
user["likes birds"] = true;
// get
alert(user["likes birds"]); // true
// delete
delete user["likes birds"];
Maintenant tout va bien. Veuillez noter que la chaĂźne de caractĂšres entre crochets est correctement entourĂ©e de quotes (tout type de guillemets fera lâaffaire).
Les crochets fournissent Ă©galement un moyen dâobtenir le nom de la propriĂ©tĂ© comme rĂ©sultat de toute expression (par opposition Ă une chaĂźne de caractĂšres littĂ©rale), semblable Ă une variable, comme ceci :
let key = "likes birds";
// pareil que user["likes birds"] = true;
user[key] = true;
Ici, la variable key peut ĂȘtre calculĂ©e au moment de lâexĂ©cution ou dĂ©pendre de la saisie de lâutilisateur. Et ensuite, nous lâutilisons pour accĂ©der Ă la propriĂ©tĂ©. Cela nous donne beaucoup de flexibilitĂ©.
Par exemple :
let user = {
name: "John",
age: 30
};
let key = prompt("What do you want to know about the user?", "name");
// accĂšs par variable
alert( user[key] ); // John (si entré "name")
La notation par points ne peut pas ĂȘtre utilisĂ©e de la mĂȘme maniĂšre :
let user = {
name: "John",
age: 30
};
let key = "name";
alert( user.key ) // undefined
Propriétés calculées
Nous pouvons utiliser des crochets dans un objet littĂ©ral, lorsquâon crĂ©e un objet. Cela sâappelle des propriĂ©tĂ©s calculĂ©es (computed propertie).
Par exemple :
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {
[fruit]: 5, // le nom de la propriété est tiré de la variable fruit
};
alert( bag.apple ); // 5 si fruit="apple"
La signification dâune propriĂ©tĂ© calculĂ©e est simple: [fruit] signifie que le nom de la propriĂ©tĂ© doit ĂȘtre extrait de fruit.
Ainsi, si un visiteur entre "apple", bag deviendra {apple: 5}.
Essentiellement, cela fonctionne de la mĂȘme façon que :
let fruit = prompt("Which fruit to buy?", "apple");
let bag = {};
// prendre le nom de la propriété de la variable fruit
bag[fruit] = 5;
⊠Mais a une meilleure apparence.
Nous pouvons utiliser des expressions plus complexes entre crochets :
let fruit = 'apple';
let bag = {
[fruit + 'Computers']: 5 // bag.appleComputers = 5
};
Les crochets sont beaucoup plus puissants que la notation par points. Ils autorisent tous les noms de propriété et variables. Mais ils sont aussi plus lourds à écrire.
Ainsi, la plupart du temps, lorsque les noms de propriété sont connus et simples, le point est utilisé. Et si nous avons besoin de quelque chose de plus complexe, nous passons aux crochets.
Valeur de propriété abrégée (Property value shorthand)
Dans du code réel, nous utilisons souvent des variables existantes en tant que valeurs pour les noms de propriétés.
Par exemple :
function makeUser(name, age) {
return {
name: name,
age: age,
// ...autres propriétés
};
}
let user = makeUser("John", 30);
alert(user.name); // John
Dans lâexemple ci-dessus, les propriĂ©tĂ©s portent les mĂȘmes noms que les variables. Le cas dâutilisation de la crĂ©ation dâune propriĂ©tĂ© Ă partir dâune variable est si courant quâil existe une valeur spĂ©ciale de propriĂ©tĂ© abrĂ©gĂ©e (property value shorthand) pour la rendre plus courte.
Au lieu de name:name, nous pouvons simplement écrire name, comme ceci :
function makeUser(name, age) {
return {
name, // pareil que name: name
age, // pareil que age: age
// ...
};
}
Nous pouvons utiliser Ă la fois des propriĂ©tĂ©s normales et des raccourcis dans le mĂȘme objet :
let user = {
name, // pareil que name:name
age: 30
};
Limitations des noms de propriété
Comme nous le savons dĂ©jĂ , une variable ne peut pas avoir un nom Ă©gal Ă lâun des mots rĂ©servĂ©s au langage comme âforâ, âletâ, âreturnâ etc.
Mais pour une propriĂ©tĂ© dâobjet, il nây a pas de telle restriction :
// ces propriétés sont toutes correctes
let obj = {
for: 1,
let: 2,
return: 3
};
alert( obj.for + obj.let + obj.return ); // 6
En bref, il nây a aucune limitation sur les noms de propriĂ©tĂ©. Il peut sâagir de nâimporte quelle chaĂźne de caractĂšres ou symbole (un type spĂ©cial pour les identifiants, qui sera traitĂ© plus tard).
Les autres types sont automatiquement convertis en chaĂźnes de caractĂšres.
Par exemple, un nombre 0 devient une chaĂźne "0" lorsquâil est utilisĂ© comme clĂ© de propriĂ©tĂ© :
let obj = {
0: "test" // identique Ă "0": "test"
};
// les 2 alertes accĂšdent Ă la mĂȘme propriĂ©tĂ© (le chiffre 0 est converti en string "0")
alert( obj["0"] ); // test
alert( obj[0] ); // test (same property)
Il y a un problÚme mineur avec une propriété spéciale nommée __proto__. Nous ne pouvons pas le définir sur une valeur non-objet :
let obj = {};
obj.__proto__ = 5; // assignation d'un nombre
alert(obj.__proto__); // [object Object] - la valeur est un objet, n'a pas fonctionné comme prévu
Comme nous le voyons dans le code, lâaffectation Ă une primitive 5 est ignorĂ©e.
Nous couvrirons la nature particuliÚre de __proto__ dans les chapitres suivants, et nous suggÚrerons une façon de corriger ce genre de comportement.
Test dâexistence de propriĂ©tĂ©, opĂ©rateur âinâ
Une caractĂ©ristique notable des objets en JavaScript, par rapport Ă de nombreux autres langages, est quâil est possible dâaccĂ©der Ă nâimporte quelle propriĂ©tĂ©. Il nây aura pas dâerreur si la propriĂ©tĂ© nâexiste pas !
La lecture dâune propriĂ©tĂ© non existante renvoie simplement undefined. Nous pouvons donc facilement tester si la propriĂ©tĂ© existe :
let user = {};
alert( user.noSuchProperty === undefined ); // true signifie "pas une telle propriété"
Il existe également un opérateur spécial "in" pour cela.
La syntaxe est :
"key" in object
Par exemple :
let user = { name: "John", age: 30 };
alert( "age" in user ); // true, user.age existe
alert( "blabla" in user ); // false, user.blabla n'existe pas
Veuillez noter que sur le cĂŽtĂ© gauche de in, il doit y avoir un nom de propriĂ©tĂ©. Câest gĂ©nĂ©ralement une chaĂźne de caractĂšres entre guillemets.
Si nous omettons les guillemets, cela signifie quâune variable doit contenir le nom rĂ©el Ă tester. Par exemple :
let user = { age: 30 };
let key = "age";
alert( key in user ); // true, la propriété "age" existe
Pourquoi lâopĂ©rateur in existe-t-il ? Nâest-ce pas suffisant de comparer avec undefined ?
Eh bien, la plupart du temps, la comparaison avec undefined fonctionne bien. Mais il y a un cas particulier quand il échoue, mais in fonctionne correctement.
Câest lorsque une propriĂ©tĂ© dâobjet existe, mais quâelle stocke undefined :
let obj = {
test: undefined
};
alert( obj.test ); // c'est indéfini, donc - pas une telle propriété ?
alert( "test" in obj ); // true, la propriété existe !
Dans le code ci-dessus, la propriĂ©tĂ© obj.test existe techniquement. Donc, lâopĂ©rateur in fonctionne bien.
Des situations comme celle-ci se produisent trĂšs rarement, parce que undefined nâest gĂ©nĂ©ralement pas attribuĂ©. Nous utilisons principalement null pour les valeurs âinconnuesâ ou âvidesâ. Ainsi, lâopĂ©rateur in est un invitĂ© exotique dans le code.
La boucle "for..in"
Pour parcourir toutes les clĂ©s dâun objet, il existe une forme spĂ©ciale de boucle : for..in. Câest une chose complĂštement diffĂ©rente de la construction for(;;) que nous avons Ă©tudiĂ©e auparavant.
La syntaxe :
for (key in object) {
// exécute le corps pour chaque clé parmi les propriétés de l'objet
}
Par exemple, affichons toutes les propriétés de user :
let user = {
name: "John",
age: 30,
isAdmin: true
};
for (let key in user) {
// keys
alert( key ); // name, age, isAdmin
// valeurs pour les clés
alert( user[key] ); // John, 30, true
}
Notez que toutes les constructions âforâ nous permettent de dĂ©clarer la variable en boucle Ă lâintĂ©rieur de la boucle, comme let key ici.
En outre, nous pourrions utiliser un autre nom de variable ici au lieu de key. Par exemple, for(let prop in obj) est également largement utilisé.
Ordonné comme un objet
Les objets sont-ils ordonnĂ©s ? En dâautres termes, si nous parcourons un objet en boucle, obtenons-nous toutes les propriĂ©tĂ©s dans le mĂȘme ordre oĂč elles ont Ă©tĂ© ajoutĂ©es ? Pouvons-nous compter sur cela ?
La rĂ©ponse courte est : âordonnĂ© de maniĂšre spĂ©cialeâ : les propriĂ©tĂ©s des entiers sont triĂ©es, les autres apparaissent dans lâordre de crĂ©ation. Nous allons voir cela en dĂ©tails.
Par exemple, considérons un objet avec les indicatifs de téléphone par pays :
let codes = {
"49": "Germany",
"41": "Switzerland",
"44": "Great Britain",
// ..,
"1": "USA"
};
for(let code in codes) {
alert(code); // 1, 41, 44, 49
}
Lâobjet peut ĂȘtre utilisĂ© pour suggĂ©rer une liste dâoptions Ă lâutilisateur. Si nous crĂ©ons un site principalement pour le public allemand, nous voulons probablement que 49 soit le premier.
Mais si nous exécutons ce code, nous voyons une image totalement différente :
- USA (1) passe en premier
- puis Switzerland (41) et ainsi de suite.
Les indicatifs de téléphone sont classés par ordre croissant, car ce sont des entiers. Donc on voit 1, 41, 44, 49.
Le terme âpropriĂ©tĂ© entierâ (integer properties) dĂ©signe ici une chaĂźne de caractĂšres qui peut ĂȘtre convertie en un nombre entier ou inversement sans changement.
Ainsi, "49" est un nom de propriĂ©tĂ© entier, parce que lorsquâil est transformĂ© en nombre entier et inversement, il reste identique. Mais "+49" et "1.2" ne le sont pas :
// Number(...) convertit explicitement en nombre
// Math.trunc est une fonction intégrée qui supprime la partie décimale
alert( String(Math.trunc(Number("49"))) ); // "49", identique, propriété entiÚre
alert( String(Math.trunc(Number("+49"))) ); // "49", non identique "+49" â propriĂ©tĂ© non entiĂšre
alert( String(Math.trunc(Number("1.2"))) ); // "1", non identique "1.2" â propriĂ©tĂ© non entiĂšre
⊠Par contre, si les clĂ©s ne sont pas des entiers, elles sont listĂ©es dans lâordre de crĂ©ation, par exemple :
let user = {
name: "John",
surname: "Smith"
};
user.age = 25; // Ajouter une clé de plus
// les propriétés non-entiers sont listées dans l'ordre de création
for (let prop in user) {
alert( prop ); // name, surname, age
}
Donc, pour rĂ©soudre le problĂšme avec les indicatifs de tĂ©lĂ©phone, nous pouvons âtricherâ en rendant ces indicatifs non entiers. Ajouter un signe plus "+" avant chaque indicatif suffit.
Comme ceci :
let codes = {
"+49": "Germany",
"+41": "Switzerland",
"+44": "Great Britain",
// ..,
"+1": "USA"
};
for(let code in codes) {
alert( +code ); // 49, 41, 44, 1
}
Maintenant, cela fonctionne comme prévu.
Résumé
Les objets sont des tableaux associatifs dotés de plusieurs fonctionnalités spéciales.
Ils stockent des propriĂ©tĂ©s (paires clĂ©-valeur), oĂč :
- Les clĂ©s de propriĂ©tĂ© doivent ĂȘtre des chaĂźnes de caractĂšres ou des symboles (gĂ©nĂ©ralement des chaĂźnes de caractĂšres).
- Les valeurs peuvent ĂȘtre de tout type.
Pour accéder à une propriété, nous pouvons utiliser :
- La notation par points :
obj.property. - Notation entre crochets
obj["property"]. Les crochets permettent de prendre la clĂ© Ă partir dâune variable, commeobj[varWithKey].
Opérateurs supplémentaires :
- Pour supprimer une propriété :
delete obj.prop. - Pour vérifier si une propriété avec la clé donnée existe :
"key" in obj. - Pour parcourir un objet : la boucle
for (let key in obj).
Ce que nous avons Ă©tudiĂ© dans ce chapitre sâappelle un âobjet simpleâ (plain object) ou juste Object.
Il existe de nombreux autres types dâobjets en JavaScript :
Arraypour stocker des collections de donnĂ©es ordonnĂ©es,Datepour stocker des informations sur la date et lâheure,Errorpour stocker des informations sur une erreur.- Etc.
Ils ont leurs particularitĂ©s que nous Ă©tudierons plus tard. Parfois, les gens disent quelque chose comme âtype Tableauâ ou âtype Dateâ, mais ils ne sont pas formellement propres, mais appartiennent Ă un seul type de donnĂ©es âobjetâ. Et ils lâĂ©tendent de diffĂ©rentes maniĂšres.
Les objets en JavaScript sont trĂšs puissants. Nous venons de gratter la surface dâun sujet vraiment Ă©norme. Nous allons travailler Ă©troitement avec les objets et en apprendre davantage Ă leur sujet dans dâautres parties du tutoriel.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâŠ)