La syntaxe régulière {...}
nous permet de créer un objet. Mais nous devons souvent créer de nombreux objets similaires, comme plusieurs utilisateurs ou éléments de menu, etc.
Cela peut être fait en utilisant les fonctions constructeur et l'opérateur "new"
.
Techniquement, les fonctions de constructeur sont des fonctions régulières. Il existe cependant deux conventions :
Ils sont nommés d’abord par une majuscule.
Ils doivent être exécutés uniquement avec l'opérateur "new"
.
Par exemple:
fonction Utilisateur (nom) { this.name = nom ; this.isAdmin = faux ; } let user = new User("Jack"); alert(utilisateur.nom); // Jacques alerte (utilisateur.isAdmin); // FAUX
Lorsqu'une fonction est exécutée avec new
, elle effectue les étapes suivantes :
Un nouvel objet vide est créé et affecté à this
.
Le corps de la fonction s'exécute. Habituellement, il modifie this
, y ajoute de nouvelles propriétés.
La valeur de this
est renvoyée.
En d'autres termes, new User(...)
fait quelque chose comme :
fonction Utilisateur (nom) { // ceci = {} ; (implicitement) // ajoute des propriétés à ceci this.name = nom ; this.isAdmin = faux ; // renvoie ceci ; (implicitement) }
Alors let user = new User("Jack")
donne le même résultat que :
laissez l'utilisateur = { nom : "Jack", isAdmin : faux } ;
Maintenant, si nous voulons créer d'autres utilisateurs, nous pouvons appeler new User("Ann")
, new User("Alice")
et ainsi de suite. Beaucoup plus court que d'utiliser des littéraux à chaque fois, et également facile à lire.
C'est l'objectif principal des constructeurs : implémenter du code de création d'objets réutilisables.
Notons encore une fois – techniquement, n'importe quelle fonction (sauf les fonctions fléchées, car elles n'en ont this
) peut être utilisée comme constructeur. Il peut être exécuté avec new
, et il exécutera l'algorithme ci-dessus. La « lettre majuscule d'abord » est un accord commun, pour indiquer clairement qu'une fonction doit être exécutée avec new
.
nouvelle fonction() { … }
Si nous avons plusieurs lignes de code consacrées à la création d'un seul objet complexe, nous pouvons les envelopper dans une fonction constructeur immédiatement appelée, comme ceci :
// crée une fonction et l'appelle immédiatement avec new laissez l'utilisateur = nouvelle fonction() { this.name = "Jean" ; this.isAdmin = faux ; // ...autre code pour la création d'utilisateurs // peut-être une logique et des instructions complexes // variables locales, etc. } ;
Ce constructeur ne peut plus être appelé, car il n'est enregistré nulle part, juste créé et appelé. Cette astuce vise donc à encapsuler le code qui construit l’objet unique, sans réutilisation future.
Trucs avancés
La syntaxe de cette section est rarement utilisée, ignorez-la sauf si vous voulez tout savoir.
À l’intérieur d’une fonction, nous pouvons vérifier si elle a été appelée avec new
ou sans, en utilisant une propriété spéciale new.target
.
Il n'est pas défini pour les appels réguliers et est égal à la fonction si elle est appelée avec new
:
fonction Utilisateur() { alerte (nouveau.target); } // sans "nouveau" : Utilisateur(); // non défini // avec "nouveau" : nouvel utilisateur (); // fonction Utilisateur { ... }
Cela peut être utilisé à l'intérieur de la fonction pour savoir si elle a été appelée avec new
, « en mode constructeur », ou sans elle, « en mode régulier ».
Nous pouvons également passer des appels new
et réguliers pour faire de même, comme ceci :
fonction Utilisateur (nom) { if (!new.target) { // si tu me lances sans new renvoyer un nouvel utilisateur (nom); // ...j'en ajouterai du nouveau pour vous } this.name = nom ; } laissez john = Utilisateur("John"); // redirige l'appel vers un nouvel utilisateur alert(john.nom); // John
Cette approche est parfois utilisée dans les bibliothèques pour rendre la syntaxe plus flexible. Pour que les gens puissent appeler la fonction avec ou sans new
, et cela fonctionne toujours.
Ce n'est probablement pas une bonne chose à utiliser partout, car l'omission new
rend un peu moins évident ce qui se passe. Avec new
nous savons tous que le nouvel objet est en cours de création.
Habituellement, les constructeurs n'ont pas d'instruction return
. Leur tâche est d'écrire tous les éléments nécessaires dans this
, et cela devient automatiquement le résultat.
Mais s’il existe une instruction return
, alors la règle est simple :
Si return
est appelé avec un objet, alors l'objet est renvoyé à la place de this
.
Si return
est appelé avec une primitive, il est ignoré.
En d'autres termes, return
with an object renvoie cet objet, dans tous les autres cas, this
est renvoyé.
Par exemple, ici return
remplace this
en renvoyant un objet :
fonction BigUser() { this.name = "Jean" ; return { nom : "Godzilla" } ; // <-- renvoie cet objet } alert( new BigUser().name ); // Godzilla, j'ai récupéré cet objet
Et voici un exemple avec un return
vide (ou nous pourrions placer une primitive après, peu importe) :
fonction PetitUtilisateur() { this.name = "Jean" ; retour; // <-- renvoie ceci } alert( new SmallUser().name ); // John
Habituellement, les constructeurs n'ont pas d'instruction return
. Nous mentionnons ici le comportement spécial avec le retour d'objets principalement par souci d'exhaustivité.
Omettre les parenthèses
D'ailleurs, on peut omettre les parenthèses après new
:
let user = nouvel utilisateur ; // <-- pas de parenthèses // pareil que let user = nouvel utilisateur ();
Omettre les parenthèses ici n'est pas considéré comme un « bon style », mais la syntaxe est autorisée par la spécification.
L'utilisation de fonctions constructeur pour créer des objets offre une grande flexibilité. La fonction constructeur peut avoir des paramètres qui définissent comment construire l'objet et ce qu'il faut y mettre.
Bien entendu, nous pouvons ajouter à this
non seulement des propriétés, mais également des méthodes.
Par exemple, new User(name)
ci-dessous crée un objet avec le name
donné et la méthode sayHi
:
fonction Utilisateur (nom) { this.name = nom ; this.sayHi = fonction() { alert( "Mon nom est : " + this.name ); } ; } let john = new User("John"); john.sayHi(); // Je m'appelle : Jean /* Jean = { nom : "Jean", disBonjour : function() { ... } } */
Pour créer des objets complexes, il existe une syntaxe plus avancée, les classes, que nous aborderons plus tard.
Les fonctions constructeurs ou, en bref, les constructeurs, sont des fonctions régulières, mais il existe un accord commun pour les nommer d'abord avec une majuscule.
Les fonctions constructeur ne doivent être appelées qu’en utilisant new
. Un tel appel implique une création de this
vide au début et le retour de celui peuplé à la fin.
Nous pouvons utiliser des fonctions constructeur pour créer plusieurs objets similaires.
JavaScript fournit des fonctions de constructeur pour de nombreux objets de langage intégrés : comme Date
pour les dates, Set
pour les ensembles et d'autres que nous prévoyons d'étudier.
Objets, nous reviendrons !
Dans ce chapitre, nous couvrons uniquement les bases des objets et des constructeurs. Ils sont essentiels pour en savoir plus sur les types de données et les fonctions dans les prochains chapitres.
Après avoir appris cela, nous revenons aux objets et les abordons en profondeur dans les chapitres Prototypes, héritage et Classes.
importance : 2
Est-il possible de créer des fonctions A
et B
pour que new A() == new B()
?
fonction A() { ... } fonction B() { ... } soit a = nouveau A(); soit b = nouveau B(); alerte( a == b ); // vrai
Si tel est le cas, fournissez un exemple de leur code.
Oui, c'est possible.
Si une fonction renvoie un objet, alors new
le renvoie à la place de this
.
Ainsi, ils peuvent, par exemple, renvoyer le même objet obj
défini en externe :
soit obj = {} ; fonction A() { return obj; } fonction B() { return obj; } alerte( new A() == new B() ); // vrai
importance : 5
Créez une fonction constructeur Calculator
qui crée des objets avec 3 méthodes :
read()
demande deux valeurs et les enregistre en tant que propriétés d'objet avec les noms a
et b
respectivement.
sum()
renvoie la somme de ces propriétés.
mul()
renvoie le produit de multiplication de ces propriétés.
Par exemple:
laissez calculatrice = new Calculatrice(); calculatrice.read(); alert( "Sum=" + calculatrice.sum() ); alert( "Mul=" + calculatrice.mul() );
Exécutez la démo
Ouvrez un bac à sable avec des tests.
fonction Calculatrice() { this.read = fonction() { this.a = +prompt('a?', 0); this.b = +prompt('b?', 0); } ; this.sum = fonction() { renvoie ceci.a + ceci.b; } ; this.mul = fonction() { renvoie ceci.a * ceci.b; } ; } laissez calculatrice = new Calculatrice(); calculatrice.read(); alert( "Sum=" + calculatrice.sum() ); alert( "Mul=" + calculatrice.mul() );
Ouvrez la solution avec des tests dans un bac à sable.
importance : 5
Créez une fonction constructeur Accumulator(startingValue)
.
L'objet qu'il crée doit :
Stockez la « valeur actuelle » dans la value
de la propriété. La valeur de départ est définie sur l'argument du constructeur startingValue
.
La méthode read()
doit utiliser prompt
pour lire un nouveau nombre et l'ajouter à value
.
En d'autres termes, la propriété value
est la somme de toutes les valeurs saisies par l'utilisateur avec la valeur initiale startingValue
.
Voici la démo du code :
laissez accumulateur = new Accumulateur (1); // valeur initiale 1 accumulateur.read(); // ajoute la valeur saisie par l'utilisateur accumulateur.read(); // ajoute la valeur saisie par l'utilisateur alert(accumulateur.value); // montre la somme de ces valeurs
Exécutez la démo
Ouvrez un bac à sable avec des tests.
fonction Accumulateur (startingValue) { this.value = valeur de départ ; this.read = fonction() { this.value += +prompt('Combien ajouter ?', 0); } ; } laissez accumulateur = new Accumulateur (1); accumulateur.read(); accumulateur.read(); alert(accumulateur.value);
Ouvrez la solution avec des tests dans un bac à sable.