Nouveaux champs de classe privée de JavaScript et comment les utiliser –
ES6 a introduit les classes dans JavaScript, mais elles sont trop simplistes pour les applications complexes. Les champs de classe (également appelés propriétés de classe ) visent à fournir des constructeurs plus simples avec des membres privés et statiques. La proposition est actuellement à TC39 étape 3: candidate et pourrait apparaître dans ES2019 (ES10).
Un récapitulatif rapide des classes ES6 est utile avant d'examiner les champs de classe plus en détail.
Classe ES6 Notions de base
Le modèle d'héritage prototypique de JavaScript peut sembler déroutant aux développeurs avec une compréhension de l'héritage classique utilisé dans des langages tels que C ++, C #, Java et PHP. Les classes JavaScript sont principalement du sucre syntaxique, mais elles offrent des concepts de programmation orientés objet plus familiers.
Une classe est un modèle qui définit comment les objets de ce type se comportent. La classe Animal
suivante définit les animaux génériques (les classes sont normalement notées avec un capital initial pour les distinguer des objets et autres types):
class Animal {
constructeur (name = 'anonyme', jambes = 4, bruit = 'rien') {
this.type = 'animal';
this.name = nom;
this.legs = jambes;
this.noise = bruit;
}
parler() {
console.log (`$ {this.name} dit" $ {this.noise} "`);
}
marche() {
console.log (`$ {this.name} marche sur $ {this.legs} legs`);
}
}
Les déclarations de classe s'exécutent en mode strict; inutile d'ajouter 'use strict'
.
Une méthode de constructeur
est exécutée lorsqu'un objet de ce type est créé et définit généralement les propriétés initiales. speak ()
et walk ()
sont des méthodes qui ajoutent d'autres fonctionnalités
Un objet peut maintenant être créé à partir de cette classe avec le nouveau mot-clé
: [19659006] const rex = nouvel animal ('Rex', 4, 'woof');
rex.speak (); // Rex dit "woof"
rex.noise = 'growl';
rex.speak (); // Rex dit "grogner"
Getters et Setters
Setters sont des méthodes spéciales utilisées pour définir des valeurs uniquement. De même, Getters sont des méthodes spéciales utilisées pour renvoyer une valeur uniquement. Par exemple:
class Animal {
constructeur (name = 'anonyme', jambes = 4, bruit = 'rien') {
this.type = 'animal';
this.name = nom;
this.legs = jambes;
this.noise = bruit;
}
parler() {
console.log (`$ {this.name} dit" $ {this.noise} "`);
}
marche() {
console.log (`$ {this.name} marche sur $ {this.legs} legs`);
}
// setter
set mange (nourriture) {
this.food = nourriture;
}
// getter
Obtenir le dîner() {
return $ {this.name} mange $ {this.food || «rien»} pour le dîner. »
}
}
const rex = nouvel animal ('Rex', 4, 'woof');
rex.eats = 'n'importe quoi';
console.log (rex.dinner); // Rex mange n'importe quoi pour le dîner.
Enfant ou sous-classes
Il est souvent pratique d'utiliser une classe comme base pour une autre. Si nous créons principalement des objets-chiens, Animal
est trop générique, et nous devons spécifier les mêmes valeurs par défaut de 4-leg et de "woof"
Dog
peut hériter toutes les propriétés et méthodes de la classe Animal
en utilisant étend
. Les propriétés et méthodes spécifiques au chien peuvent être ajoutées ou supprimées si nécessaire:
class Dog extends Animal {
constructeur (nom) {
// appelle le constructeur Animal
super (nom, 4, 'woof');
this.type = 'chien';
}
// remplacer Animal.speak
parler (à) {
super.speak ();
if (to) console.log (`à $ {à}`);
}
}
super
fait référence à la classe parent et est généralement appelé dans le constructeur
. Dans cet exemple, la méthode Dog speak ()
remplace celle définie dans Animal
.
Des instances d'objet de Dog
peuvent maintenant être créées:
const rex = nouveau chien ('Rex');
rex.speak ('tout le monde'); // Rex dit "woof" à tout le monde
rex.eats = 'n'importe quoi';
console.log (rex.dinner); // Rex mange n'importe quoi pour le dîner.
Méthodes et propriétés statiques
La définition d'une méthode avec le mot clé statique
permet de l'appeler sur une classe sans créer d'instance d'objet. JavaScript ne supporte pas les propriétés statiques de la même manière que les autres langages, mais il est possible d'ajouter des propriétés à la définition de la classe (une classe
est un objet JavaScript en soi!).
] La classe Dog peut être adaptée pour retenir le nombre d'objets dog créés:
class Dog extends Animal {
constructeur (nom) {
// appelle le constructeur Animal
super (nom, 4, 'woof');
this.type = 'chien';
// met à jour le nombre d'objets Chien
Dog.count ++;
}
// remplacer Animal.speak
parler (à) {
super.speak ();
if (to) console.log (`à $ {à}`);
}
// renvoie le nombre d'objets chien
static obtient COUNT () {
retourner Dog.count;
}
}
// propriété statique (ajoutée après la définition de la classe)
Dog.count = 0;
Le getter COUNT
statique de la classe renvoie le nombre de chiens créés:
console.log (`Dogs defined: $ {Dog.COUNT}`); // Chiens définis: 0
const don = new Chien ('Don');
console.log (`Dogs defined: $ {Dog.COUNT}`); // Chiens définis: 1
const kim = nouveau chien ('Kim');
console.log (`Dogs defined: $ {Dog.COUNT}`); // Chiens définis: 2
Pour plus d'informations, reportez-vous à JavaScript orienté objet: Plongée profonde dans les classes ES6 .
Champs de classe ESnext
La proposition de champs de classe permet d'initialiser les propriétés en haut d'un class:
classe MyClass {
a = 1;
b = 2;
c = 3;
}
Ceci est équivalent à:
class MyClass {
constructeur () {
this.a = 1;
this.b = 2;
this.c = 3;
}
}
Les initialiseurs sont exécutés avant tout constructeur ( en supposant qu'un constructeur est toujours nécessaire ).
Champs de classes statiques
Les champs de classe permettent de déclarer des propriétés statiques dans la classe
] Par exemple:
class MyClass {
x = 1;
y = 2;
statique z = 3;
}
console.log (MyClass.z); // 3
L'équivalent ES6 inélégant:
class MyClass {
constructeur () {
this.x = 1;
this.y = 2;
}
}
MyClass.z = 3;
console.log (MyClass.z); // 3
Champs de classe privée
Toutes les propriétés des classes ES6 sont publiques par défaut et peuvent être examinées ou modifiées en dehors de la classe. Dans l'exemple Animal
ci-dessus, rien n'empêche que la propriété food
soit changée sans appeler le setter mange
:
class Animal {
constructeur (name = 'anonyme', jambes = 4, bruit = 'rien') {
this.type = 'animal';
this.name = nom;
this.legs = jambes;
this.noise = bruit;
}
set mange (nourriture) {
this.food = nourriture;
}
Obtenir le dîner() {
return $ {this.name} mange $ {this.food || «rien»} pour le dîner. »
}
}
const rex = nouvel animal ('Rex', 4, 'woof');
rex.eats = 'n'importe quoi'; // setter standard
rex.food = 'tofu'; // contournent le setters de mange tout à fait
console.log (rex.dinner); // Rex mange du tofu pour le dîner.
D'autres langues permettent de déclarer private
propriétés. Ce n'est pas possible dans ES6, bien que les développeurs puissent le contourner en utilisant une convention de soulignement ( _propertyName
), fermetures, symboles ou WeakMaps .
Dans ESnext, les champs de classe privés sont définis en utilisant un hash #
préfixe:
class MyClass {
a = 1; // .a est public
#b = 2; //. # b est privé
statique #c = 3; //. # c est privé et statique
incB () {
ceci. # b ++;
}
}
const m = nouveau MyClass ();
m.incB (); // fonctionne bien
m. # b = 0; // erreur - la propriété privée ne peut pas être modifiée en dehors de la classe
Notez qu'il n'y a aucun moyen de définir des méthodes privées, des getters et des setters, bien qu'un TC39 stage 2: draft proposition suggère d'utiliser un préfixe hash #
sur les noms. Par exemple:
class MyClass {
// propriété privée
#x = 0;
// méthode privée (ne peut être appelée que dans la classe)
#incX () {
ceci. # x ++;
}
// setter privé (ne peut être appelé que dans la classe)
set #setX (x) {
ceci. # x = x;
}
// getter privé (ne peut être appelé que dans la classe)
get #getX () {
retourne ceci. $ x;
}
}
Les composants React ont souvent des méthodes liées aux événements DOM. Pour assurer que
résout le composant, il faut lier
toutes les méthodes en conséquence. Par exemple:
class App extends Component {
constructeur () {
super();
état = {nombre: 0};
// lie toutes les méthodes
this.incCount = this.incCount.bind (this);
}
incCount () {
this.setState (ps => ({count: ps.count + 1}));
}
render () {
revenir (
{this.state.count}
);
}
}
Si incCount
est défini comme un champ de classe, il peut être défini sur une fonction à l'aide d'une grosse flèche ES6 =>
qui le lie automatiquement à l'objet de définition. L'état
peut également être déclaré en tant que champ de classe, donc aucun constructeur n'est requis:
class App extends Component {
état = {nombre: 0};
incCount = () => {
this.setState (ps => ({count: ps.count + 1}));
}
render () {
revenir (
{this.state.count}
);
}
}
Utilisation de champs de classe aujourd'hui
Les champs de classe ne sont actuellement pas pris en charge dans les navigateurs ou Node.js. Cependant, il est possible de transpiler la syntaxe en utilisant Babel qui est activé par défaut en utilisant Create React App . Alternativement, Babel peut être installé et configuré en utilisant les commandes de terminal suivantes:
mkdir class-properties
cd class-properties
npm init -y
npm installer --save-dev babel-cli babel-plugin-transform-class-properties
echo '{"plugins": ["transform-class-properties"]}'> .babelrc
Ajouter une commande build
à la section scripts
de package.json
:
"scripts": {
"build": "babel in.js -o out.js"
},
Puis lancez avec npm run build
pour transférer le fichier ESnext in.js
vers un fichier compatible avec le navigateur croisé out.js
.
Babel support pour méthodes privées, getters et setters a été proposé
Champs de classe: une amélioration?
Les définitions de classe ES6 étaient simplistes. Les champs de classe devraient faciliter la lisibilité et permettre certaines options intéressantes. Je n'aime pas particulièrement utiliser un hash #
pour désigner des membres privés, mais des comportements inattendus et des problèmes de performances seraient encourus sans cela (voir les nouveaux champs #private de JavaScript pour un explication]
Peut-être que cela va de soi, mais je vais le dire quand même: les concepts discutés dans cet article sont sujets à changement et ne pourront jamais être implémentés! avoir des avantages pratiques et l'intérêt augmente. C'est un pari sûr.
Source link