Comme nous le savons dans le chapitre Types de données, il existe huit types de données en JavaScript. Sept d'entre eux sont appelés « primitifs », 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 à clé de diverses données et d'entités plus complexes. En JavaScript, les objets pénètrent presque tous les aspects du langage. Il faut donc d’abord les comprendre avant d’aller en profondeur ailleurs.
Un objet peut être créé avec des crochets de chiffres {…}
avec une liste facultative de propriétés . Une propriété est une paire « clé : valeur », où key
est une chaîne (également appelée « nom de propriété ») et value
peut être n'importe quoi.
On peut imaginer un objet comme un meuble avec des dossiers 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 :
laissez l'utilisateur = new Object(); // Syntaxe du "constructeur d'objet" laissez l'utilisateur = {} ; // Syntaxe "objet littéral"
Habituellement, les parenthèses de chiffres {...}
sont utilisées. Cette déclaration est appelée un objet littéral .
Nous pouvons immédiatement mettre certaines propriétés dans {...}
sous forme de paires « clé : valeur » :
let user = { // un objet name : "John", // par clé "name" stocke la valeur "John" age : 30 // par clé "age" valeur de magasin 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"
.
Le second porte le nom "age"
et la valeur 30
.
L'objet user
résultant peut être imaginé comme une armoire avec deux fichiers signés étiquetés « nom » et « âge ».
Nous pouvons y ajouter, supprimer et lire des fichiers à tout moment.
Les valeurs des propriétés sont accessibles à l'aide de la notation par points :
// récupère les valeurs des propriétés de l'objet : alert( utilisateur.nom ); // John alert( utilisateur.age ); // 30
La valeur peut être de n'importe quel type. Ajoutons un booléen :
utilisateur.isAdmin = vrai ;
Pour supprimer une propriété, nous pouvons utiliser l'opérateur delete
:
supprimer l'utilisateur.age ;
Nous pouvons également utiliser des noms de propriétés multimots, mais ils doivent alors être cités :
laissez l'utilisateur = { nom : "Jean", âge : 30 ans, "aime les oiseaux": vrai // le nom de la propriété multi-mots doit être cité } ;
La dernière propriété de la liste peut se terminer par une virgule :
laissez l'utilisateur = { nom : "Jean", âge : 30 ans, }
C'est ce qu'on appelle une virgule « de fin » ou « suspendue ». Facilite l'ajout/suppression/déplacement de propriétés, car toutes les lignes se ressemblent.
Pour les propriétés multimots, l'accès aux points ne fonctionne pas :
// cela donnerait une erreur de syntaxe user.likes oiseaux = vrai
JavaScript ne comprend pas cela. Il pense que nous nous adressons à user.likes
, puis donne une erreur de syntaxe lorsqu'il rencontre birds
inattendus.
Le point nécessite que la clé soit un identifiant de variable valide. Cela implique : 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 :
laissez l'utilisateur = {} ; // ensemble user["aime les oiseaux"] = true; // obtenir alert(user["aime les oiseaux"]); // vrai // supprimer supprimer l'utilisateur["aime les oiseaux"] ;
Maintenant, tout va bien. Veuillez noter que la chaîne entre parenthèses est correctement citée (n'importe quel type de guillemets fera l'affaire).
Les crochets fournissent également un moyen d'obtenir le nom de la propriété comme résultat d'une expression - par opposition à une chaîne littérale - comme à partir d'une variable comme suit :
let key = "aime les oiseaux" ; // identique à user["aime les oiseaux"] = true; utilisateur[clé] = vrai ;
Ici, la key
variable peut être calculée au moment de l'exécution ou dépendre de la saisie de l'utilisateur. Et puis nous l'utilisons pour accéder à la propriété. Cela nous donne une grande flexibilité.
Par exemple:
laissez l'utilisateur = { nom : "Jean", âge : 30 ans } ; let key = prompt("Que voulez-vous savoir sur l'utilisateur ?", "nom"); // accès par variable alert( utilisateur[clé] ); // John (si entrez "nom")
La notation par points ne peut pas être utilisée de la même manière :
laissez l'utilisateur = { nom : "Jean", âge : 30 ans } ; let key = "nom"; alert( user.key ) // non défini
Nous pouvons utiliser des crochets dans un objet littéral, lors de la création d'un objet. C'est ce qu'on appelle les propriétés calculées .
Par exemple:
let fruit = prompt("Quel fruit acheter ?", "pomme"); laisser le sac = { [fruit] : 5, // le nom de la propriété est tiré de la variable fruit } ; alerte( sac.apple ); // 5 si fruit="pomme"
La signification d'une propriété calculée est simple : [fruit]
signifie que le nom de la propriété doit être tiré de fruit
.
Ainsi, si un visiteur saisit "apple"
, bag
deviendra {apple: 5}
.
En gros, cela fonctionne de la même manière que :
let fruit = prompt("Quel fruit acheter ?", "pomme"); laissez le sac = {} ; // prend le nom de la propriété de la variable fruit sac[fruit] = 5 ;
… Mais ça a l'air plus joli.
Nous pouvons utiliser des expressions plus complexes entre crochets :
soit fruit = 'pomme'; laisser le sac = { [fruit + 'Ordinateurs'] : 5 // bag.appleComputers = 5 } ;
Les crochets sont beaucoup plus puissants que la notation par points. Ils autorisent tous les noms de propriétés et variables. Mais ils sont aussi plus lourds à rédiger.
Ainsi la plupart du temps, lorsque les noms de propriétés sont connus et simples, le point est utilisé. Et si nous avons besoin de quelque chose de plus complexe, nous passons aux crochets.
Dans le code réel, nous utilisons souvent des variables existantes comme valeurs pour les noms de propriétés.
Par exemple:
function makeUser (nom, âge) { retour { nom : nom, âge: âge, // ...autres propriétés } ; } let user = makeUser("Jean", 30); alert(utilisateur.nom); // John
Dans l'exemple ci-dessus, les propriétés portent les mêmes noms que les variables. Le cas d'utilisation consistant à créer une propriété à partir d'une variable est si courant qu'il existe un raccourci spécial pour la valeur de la propriété pour la rendre plus courte.
Au lieu de name:name
nous pouvons simplement écrire name
, comme ceci :
function makeUser (nom, âge) { retour { nom, // identique à nom : nom âge, // identique à âge : âge //... } ; }
Nous pouvons utiliser à la fois des propriétés normales et des raccourcis dans le même objet :
laissez l'utilisateur = { nom, // identique à nom:nom âge : 30 ans } ;
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 « pour », « laisser », « retourner », etc.
Mais pour une propriété d'objet, il n'y a pas une telle restriction :
// ces propriétés sont bonnes soit obj = { pour : 1, soit : 2, retour : 3 } ; alert( obj.for + obj.let + obj.return ); // 6
En bref, il n'y a aucune limitation sur les noms de propriétés. Il peut s'agir de n'importe quelle chaîne ou symbole (un type spécial pour les identifiants, qui sera abordé plus tard).
Les autres types sont automatiquement convertis en chaînes.
Par exemple, un nombre 0
devient une chaîne "0"
lorsqu'il est utilisé comme clé de propriété :
soit obj = { 0 : "test" // identique à "0": "test" } ; // les deux alertes accèdent à la même propriété (le chiffre 0 est converti en chaîne "0") alerte( obj["0"] ); // test alerte( obj[0] ); // test (même propriété)
Il y a un piège mineur avec une propriété spéciale nommée __proto__
. Nous ne pouvons pas le définir sur une valeur non-objet :
soit obj = {} ; obj.__proto__ = 5; // attribue un numéro alerte(obj.__proto__); // [object Object] - la valeur est un objet, n'a pas fonctionné comme prévu
Comme le montre le code, l'affectation à une primitive 5
est ignorée.
Nous aborderons la nature particulière de __proto__
dans les chapitres suivants et suggérerons des moyens de corriger un tel comportement.
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é inexistante renvoie simplement undefined
. On peut donc facilement tester si la propriété existe :
laissez l'utilisateur = {} ; alert( user.noSuchProperty === non défini ); // true signifie "aucune propriété de ce type"
Il existe également un opérateur spécial "in"
pour cela.
La syntaxe est :
"clé" dans l'objet
Par exemple:
let user = { nom : "John", âge : 30 } ; alert( "âge" dans l'utilisateur ); // vrai, user.age existe alert( "blabla" dans l'utilisateur ); // faux, 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 entre guillemets.
Si nous omettons les guillemets, cela signifie qu'une variable doit contenir le nom réel à tester. Par exemple:
laissez l'utilisateur = { âge : 30 } ; let key = "âge"; alert( entrez l'utilisateur ); // vrai, la propriété "age" existe
Pourquoi l'opérateur in
existe-t-il ? N'est-il pas suffisant de comparer avec undefined
?
Eh bien, la plupart du temps, la comparaison avec undefined
fonctionne correctement. Mais il existe un cas particulier où cela échoue, mais "in"
fonctionne correctement.
C'est lorsqu'une propriété d'objet existe, mais stocke undefined
:
soit obj = { test : non défini } ; alerte( obj.test ); // ce n'est pas défini, donc - pas de telle propriété ? alert( "test" dans obj ); // vrai, la propriété existe !
Dans le code ci-dessus, la propriété obj.test
existe techniquement. L'opérateur in
fonctionne donc correctement.
Des situations comme celle-ci se produisent très rarement, car undefined
ne doit pas être explicitement attribué. Nous utilisons principalement null
pour les valeurs « inconnues » ou « vides ». L'opérateur in
est donc un invité exotique dans le code.
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 :
pour (clé dans l'objet) { // exécute le corps de chaque clé parmi les propriétés de l'objet }
Par exemple, affichons toutes les propriétés de user
:
laissez l'utilisateur = { nom : "Jean", âge : 30 ans, isAdmin : vrai } ; pour (laisser la clé dans l'utilisateur) { // clés alerte( clé ); // nom, âge, isAdmin // valeurs pour les clés alert( utilisateur[clé] ); // Jean, 30 ans, vrai }
Notez que toutes les constructions « for » nous permettent de déclarer la variable de boucle à l'intérieur de la boucle, comme let key
ici.
De plus, nous pourrions utiliser ici un autre nom de variable au lieu de key
. Par exemple, "for (let prop in obj)"
est également largement utilisé.
Les objets sont-ils commandés ? En d’autres termes, si nous parcourons un objet, obtenons-nous toutes les propriétés dans le même ordre dans lequel elles ont été ajoutées ? Pouvons-nous nous y fier ?
La réponse courte est : « ordonnées d'une manière spéciale » : les propriétés entières sont triées, les autres apparaissent dans l'ordre de création. Les détails suivent.
A titre d'exemple, considérons un objet avec les codes téléphoniques :
soit les codes = { "49": "Allemagne", "41": "Suisse", "44": "Grande-Bretagne", // .., "1": "Etats-Unis" } ; pour (laisser le code dans les codes) { alerte(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 destiné à un public allemand, nous souhaitons probablement que 49
soit le premier.
Mais si nous exécutons le code, nous voyons une image totalement différente :
Les États-Unis (1) passent en premier
puis la Suisse (41) et ainsi de suite.
Les codes téléphoniques sont triés par ordre croissant, car ce sont des nombres entiers. Nous voyons donc 1, 41, 44, 49
.
Propriétés entières ? Qu'est ce que c'est?
Le terme « propriété entière » désigne ici une chaîne qui peut être convertie vers et depuis un entier sans modification.
Ainsi, "49"
est un nom de propriété entier, car lorsqu'il est transformé en nombre entier et inversement, c'est toujours le même. Mais "+49"
et "1.2"
ne le sont pas :
// Number(...) se convertit explicitement en nombre // Math.trunc est une fonction intégrée qui supprime la partie décimale alerte( String(Math.trunc(Number("49"))) ); // "49", idem, propriété entière alerte( String(Math.trunc(Number("+49"))) ); // "49", pas pareil "+49" ⇒ propriété non entière alert( String(Math.trunc(Number("1.2"))) ); // "1", pas la même chose "1.2" ⇒ propriété non entière
…En revanche, si les clés ne sont pas entières, alors elles sont répertoriées dans l'ordre de création, par exemple :
laissez l'utilisateur = { nom : "Jean", nom de famille : « Smith » } ; utilisateur.age = 25 ; // en ajoute un de plus // les propriétés non entières sont répertoriées dans l'ordre de création pour (laisser prop dans l'utilisateur) { alerte( accessoire ); // nom, prénom, âge }
Ainsi, pour résoudre le problème avec les codes téléphoniques, nous pouvons « tricher » en rendant les codes non entiers. Il suffit d'ajouter un signe plus "+"
avant chaque code.
Comme ça:
soit les codes = { "+49": "Allemagne", "+41": "Suisse", "+44": "Grande-Bretagne", // .., "+1": "États-Unis" } ; pour (laisser le code dans les codes) { alerte( +code ); // 49, 41, 44, 1 }
Maintenant, cela fonctionne comme prévu.
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 ou des symboles (généralement des chaînes).
Les valeurs peuvent être de n’importe quel 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é d'une variable, comme obj[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 : boucle for (let key in obj)
.
Ce que nous avons étudié dans ce chapitre s'appelle un « objet simple », ou simplement Object
.
Il existe de nombreux autres types d'objets en JavaScript :
Array
pour stocker des collections de données ordonnées,
Date
pour stocker les informations sur la date et l'heure,
Error
pour stocker les informations sur une erreur.
…Et ainsi de suite.
Ils ont leurs particularités que nous étudierons plus tard. Parfois, les gens disent quelque chose comme « Type de tableau » ou « Type de date », mais formellement, ce ne sont pas des types qui leur sont propres, mais appartiennent à un seul type de données « objet ». Et ils l’étendent de diverses manières.
Les objets en JavaScript sont très puissants. Nous venons ici d'effleurer la surface d'un sujet vraiment énorme. Nous travaillerons en étroite collaboration avec des objets et en apprendrons davantage à leur sujet dans les autres parties du didacticiel.
importance : 5
Écrivez le code, une ligne pour chaque action :
Créez un user
d'objet vide .
Ajoutez le name
de la propriété avec la valeur John
.
Ajoutez le surname
de propriété avec la valeur Smith
.
Remplacez la valeur du name
par Pete
.
Supprimez le name
de la propriété de l'objet.
laissez l'utilisateur = {} ; nom d'utilisateur = "Jean" ; utilisateur.nom = "Smith"; nom d'utilisateur = "Pete" ; supprimer user.name ;
importance : 5
Écrivez la fonction isEmpty(obj)
qui renvoie true
si l'objet n'a pas de propriétés, false
sinon.
Cela devrait fonctionner comme ça :
laissez planning = {} ; alert( isEmpty(calendrier) ); // vrai planning["8:30"] = "lève-toi"; alert( isEmpty(calendrier) ); // FAUX
Ouvrez un bac à sable avec des tests.
Faites simplement une boucle sur l'objet et return false
s'il y a au moins une propriété.
la fonction estEmpty(obj) { pour (laisser la clé dans obj) { // si la boucle a démarré, il y a une propriété renvoie faux ; } renvoie vrai ; }
Ouvrez la solution avec des tests dans un bac à sable.
importance : 5
Nous avons un objet stockant les salaires de notre équipe :
laissez les salaires = { Jean : 100, Anne : 160, Pierre : 130 }
Écrivez le code pour additionner tous les salaires et stockez-le dans la variable sum
. Doit être 390
dans l’exemple ci-dessus.
Si salaries
est vide, alors le résultat doit être 0
.
laissez les salaires = { Jean : 100, Anne : 160, Pierre : 130 } ; soit somme = 0 ; pour (laisser saisir les salaires) { somme += salaires[clé] ; } alerte (somme); // 390
importance : 3
Créez une fonction multiplyNumeric(obj)
qui multiplie toutes les valeurs de propriété numérique de obj
par 2
.
Par exemple:
// avant l'appel laissez menu = { largeur : 200, hauteur : 300, titre : "Mon menu" } ; multiplierNumeric(menu); // après l'appel menu = { largeur : 400, hauteur : 600, titre : "Mon menu" } ;
Veuillez noter que multiplyNumeric
n'a pas besoin de renvoyer quoi que ce soit. Il devrait modifier l'objet sur place.
PS Utilisez typeof
pour vérifier un numéro ici.
Ouvrez un bac à sable avec des tests.
function multiplierNumeric(obj) { pour (laisser la clé dans obj) { if (typeof obj[key] == 'numéro') { obj[clé] *= 2; } } }
Ouvrez la solution avec des tests dans un bac à sable.