Les objets sont généralement créés pour représenter des entités du monde réel, comme des utilisateurs, des commandes, etc. :
let user = {
name: "John",
age: 30
};
Et, dans le monde réel, un utilisateur peut agir : sélectionner un élément du panier, se connecter, se déconnecter, etc.
Les actions sont représentées en JavaScript par des fonctions dans les propriétés.
Exemples de méthodes
Pour commencer, apprenons à user à dire bonjour :
let user = {
name: "John",
age: 30
};
user.sayHi = function() {
alert("Hello!");
};
user.sayHi(); // Hello!
Ici, nous venons dâutiliser une fonction expression pour créer la fonction et lâaffecter à la propriété user.sayHi de lâobjet.
Ensuite, nous pouvons lâappeler comme user.sayHi(). Lâutilisateur peut maintenant parler!
Une fonction qui est la propriété dâun objet sâappelle sa méthode.
Nous avons donc ici une méthode sayHi de lâobjet user.
Bien sûr, nous pourrions utiliser une fonction pré-déclarée comme méthode, comme ceci :
let user = {
// ...
};
// d'abord, déclarer
function sayHi() {
alert("Hello!");
}
// puis ajouter comme une méthode
user.sayHi = sayHi;
user.sayHi(); // Hello!
Lorsque nous écrivons notre code en utilisant des objets pour représenter des entités, cela sâappelle une programmation orientée objet, en bref : âPOOâ.
La programmation orientée objet est un élément important, une science intéressante en soi. Comment choisir les bonnes entités ? Comment organiser lâinteraction entre elles ? Câest une architecture, et il existe dâexcellents livres sur ce sujet, tels que âDesign Patterns: Elements of Reusable Object-Oriented Softwareâ de E. Gamma, R. Helm, R. Johnson, J. Vissides ou âObject-Oriented Analysis and Design with Applicationsâ de G. Booch, et plus.
Méthode abrégée
Il existe une syntaxe plus courte pour les méthodes dans un littéral dâobjet :
// ces objets font la même chose
user = {
sayHi: function() {
alert("Hello");
}
};
// la méthode abrégée semble mieux, non ?
user = {
sayHi() { // identique à "sayHi: function(){...}"
alert("Hello");
}
};
Comme démontré, nous pouvons omettre "function" et simplement écrire sayHi().
A vrai dire, les notations ne sont pas totalement identiques. Il existe des différences subtiles liées à lâhéritage dâobjet (à couvrir plus tard), mais pour le moment, elles importent peu. Dans presque tous les cas, la syntaxe la plus courte est préférable.
âthisâ dans les méthodes
Il est courant quâune méthode dâobjet ait besoin dâaccéder aux informations stockées dans lâobjet pour effectuer son travail.
Par exemple, le code à lâintérieur de user.sayHi() peut nécessiter le nom de user.
Pour accéder à lâobjet, une méthode peut utiliser le mot-clé this.
La valeur de this est lâobjet âavant le pointâ, celui utilisé pour appeler la méthode.
Par exemple :
let user = {
name: "John",
age: 30,
sayHi() {
// "this" est "l'objet actuel"
alert(this.name);
}
};
user.sayHi(); // John
Ici, lors de lâexécution de user.sayHi(), la valeur de this sera user.
Techniquement, il est également possible dâaccéder à lâobjet sans this, en le référençant via la variable externe :
let user = {
name: "John",
age: 30,
sayHi() {
alert(user.name); // "user" au lieu de "this"
}
};
⦠Mais un tel code nâest pas fiable. Si nous décidons de copier user dans une autre variable, par exemple admin = user et écraser user avec quelque chose dâautre, il accédera au mauvais objet.
Cela est démontré ci-dessous :
let user = {
name: "John",
age: 30,
sayHi() {
alert( user.name ); // conduit à une erreur
}
};
let admin = user;
user = null; // écraser pour rendre les choses évidentes
admin.sayHi(); // TypeError: Cannot read property 'name' of null
Si nous utilisions this.name au lieu de user.name dans lâalert, le code fonctionnerait.
âthisâ nâest pas lié
En JavaScript, le mot clé this se comporte différemment de la plupart des autres langages de programmation. Il peut être utilisé dans nâimporte quelle fonction, même si ce nâest pas une méthode dâun objet.
Il nây a pas dâerreur de syntaxe dans le code suivant :
function sayHi() {
alert( this.name );
}
La valeur de this est évaluée pendant lâexécution, en fonction du contexte.
Par exemple, ici la même fonction est assignée à deux objets différents et a un âthisâ différent dans les appels :
let user = { name: "John" };
let admin = { name: "Admin" };
function sayHi() {
alert( this.name );
}
// utiliser la même fonction dans deux objets
user.f = sayHi;
admin.f = sayHi;
// ces appels ont un this différent
// "this" à l'intérieur de la fonction est l'objet "avant le point"
user.f(); // John (this == user)
admin.f(); // Admin (this == admin)
admin['f'](); // Admin (le point ou les crochets accèdent à la méthode - peu importe)
La règle est simple : si obj.f() est appelé, alors this est obj pendant lâappel de f. Câest donc lâuser ou lâadmin dans lâexemple ci-dessus.
this == undefinedNous pouvons même appeler la fonction sans objet du tout :
function sayHi() {
alert(this);
}
sayHi(); // undefined
Dans ce cas, this est undefined en mode strict. Si nous essayons dâaccéder à this.name, il y aura une erreur.
En mode non strict (si on oublie use strict), la valeur de this dans ce cas sera lâobjet global (la fenêtre dâun navigateur, nous y reviendrons plus tard). Ceci est un comportement historique que le mode strict corrige.
Ce genre dâappel est généralement une erreur de programmation. Si il y a un this dans une fonction, il sâattend à être appelée dans un contexte dâobjet.
this non liéSi vous venez dâun autre langage de programmation, vous êtes probablement habitué à lâidée dâun âthis liéâ, où les méthodes définies dans un objet ont toujours this en référence à cet objet.
En JavaScript, this est âlibreâ, sa valeur est évaluée au moment de lâappel et ne dépend pas de lâendroit où la méthode a été déclarée, mais plutôt de lâobjet âavant le pointâ.
Le concept de temps dâexécution évalué de this présente à la fois des avantages et des inconvénients. Dâune part, une fonction peut être réutilisée pour différents objets. Dâautre part, une plus grande flexibilité ouvre la place à des erreurs.
Ici, notre position nâest pas de juger si cette décision de conception linguistique est bonne ou mauvaise. Nous comprendrons comment travailler avec elle, comment obtenir des avantages et éviter les problèmes.
Les fonctions fléchées nâont pas de âthisâ
Les fonctions fléchées sont spéciales : elles nâont pas leur âpropreâ this. Si nous faisons référence à this à partir dâune telle fonction, cela provient de la fonction externe ânormaleâ.
Par exemple, ici arrow() utilise this depuis la méthode externe user.sayHi() :
let user = {
firstName: "Ilya",
sayHi() {
let arrow = () => alert(this.firstName);
arrow();
}
};
user.sayHi(); // Ilya
Câest une particularité des fonctions fléchées. Câest utile lorsque nous ne voulons pas réellement avoir un this distinct, mais plutôt le prendre à partir du contexte extérieur. Plus tard dans le chapitre Les fonctions fléchées revisitées nous allons approfondir les fonctions fléchées.
Résumé
- Les fonctions stockées dans les propriétés de lâobjet sâappellent des âméthodesâ.
- Les méthodes permettent aux objets dâagir comme
object.doSomething(). - Les méthodes peuvent référencer lâobjet comme
this.
La valeur de this est définie au moment de lâexécution.
- Lorsquâune fonction est déclarée, elle peut utiliser
this, mais cethisnâa aucune valeur jusquâà ce que la fonction soit appelée. - Une fonction peut être copiée entre des objets.
- Lorsquâune fonction est appelée dans la syntaxe âméthodeâ :
object.method(), la valeur dethislors de lâappel estobjet.
Veuillez noter que les fonctions fléchées sont spéciales : elles nâont pas this. Lorsque this est accédé dans une fonction fléchée, il est pris de lâextérieur.
Commentaires
<code>, pour plusieurs lignes â enveloppez-les avec la balise<pre>, pour plus de 10 lignes - utilisez une sandbox (plnkr, jsbin, codepenâ¦)