Maison > interface Web > js tutoriel > Les nouveaux champs de classe privée de JavaScript, et comment les utiliser

Les nouveaux champs de classe privée de JavaScript, et comment les utiliser

Joseph Gordon-Levitt
Libérer: 2025-02-10 14:30:15
original
844 Les gens l'ont consulté

JavaScript's New Private Class Fields, and How to Use Them

ES6 présente des classes pour JavaScript, mais pour des applications complexes, elles peuvent être trop simples. Les champs de classe (également appelés attribut de classe ) sont conçus pour simplifier les constructeurs avec des membres privés et statiques. La proposition est actuellement dans le stade TC39 Phase 3: candidat et sera probablement ajoutée à ES2019 (ES10). Node.js 12, Chrome 74 et Babel prennent actuellement en charge les champs privés. Avant de comprendre comment les champs de classe sont mis en œuvre, il est utile de revoir la classe ES6. Cet article a été mis à jour en 2020. Pour des connaissances JavaScript plus approfondies, lisez notre livre "JavaScript: From Newbie to Ninja, deuxième édition".

Points clés

  • ES6 présente des classes pour JavaScript, mais pour des applications complexes, elles peuvent être trop simples. Les champs de classe de l'ES2019 sont conçus pour simplifier le constructeur avec des membres privés et statiques qui peuvent être ajoutés à ES2019 (ES10).
  • La nouvelle implémentation de champ de classe permet l'initialisation des propriétés publiques en dehors de tout constructeur en haut de la classe. Si le constructeur est toujours nécessaire, l'initialisateur est exécuté avant son exécution.
  • Les champs de classe dans ES2019 permettent de déclarer les champs de classe privée à l'aide d'un préfixe de hachage #. Cela rend le champ accessible uniquement dans les méthodes intérieures de la classe, et non de l'extérieur de la classe.
  • L'utilisation de # pour représenter la confidentialité dans les champs de classe a été critiquée, principalement parce qu'elle n'est pas aussi intuitive que les mots clés privés. Cependant, le symbole # n'est pas valide en dehors de la définition de la classe, garantissant que les champs privés restent privés.
  • L'avantage immédiat des champs de classe ES2019 est le code de réaction plus propre. Ils peuvent être attribués en fonction de la flèche ES6 = & gt;

ES6 Basics de catégorie

Les développeurs de langues tels que C, C #, Java et PHP peuvent être confus par le modèle d'héritage orienté objet de JavaScript. Par conséquent, ES6 a introduit la classe . Ils sont principalement du sucre syntaxique, mais offrent un concept plus familier de programmation orientée objet. Une classe est un modèle d'objet qui définit comment les objets de ce type se comportent. La classe animale suivante définit les animaux généraux (les classes sont généralement représentées en majuscules initiaux pour les distinguer des objets et d'autres types):

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  speak() {
    console.log(`${this.name} says "${this.noise}"`);
  }

  walk() {
    console.log(`${this.name} walks on ${this.legs} legs`);
  }

}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Les déclarations de classe sont toujours exécutées en mode strict. Pas besoin d'ajouter «Utiliser Strict». La méthode du constructeur s'exécute lors de la création d'un objet de type animal. Il définit généralement les propriétés initiales et gère d'autres initialisations. Speak () et Walk () sont des méthodes d'instance qui ajoutent plus de fonctionnalités. Vous pouvez maintenant utiliser le nouveau mot clé pour créer des objets à partir de cette classe:

let rex = new Animal('Rex', 4, 'woof');
rex.speak();          // Rex says "woof"
rex.noise = 'growl';
rex.speak();          // Rex says "growl"
Copier après la connexion
Copier après la connexion

getter et seter

setter est une méthode spéciale utilisée uniquement pour définir les valeurs. De même, Getter est une méthode spéciale pour les valeurs de retour uniquement. Par exemple:

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  speak() {
    console.log(`${this.name} says "${this.noise}"`);
  }

  walk() {
    console.log(`${this.name} walks on ${this.legs} legs`);
  }

  // setter
  set eats(food) {
    this.food = food;
  }

  // getter
  get dinner() {
    return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
  }

}

let rex = new Animal('Rex', 4, 'woof');
rex.eats = 'anything';
console.log( rex.dinner );  // Rex eats anything for dinner.
Copier après la connexion
Copier après la connexion

Sous-classe ou sous-classe

Il est généralement possible d'utiliser une classe comme classe de base pour une autre. La classe humaine peut hériter de toutes les propriétés et méthodes de la classe animale en utilisant le mot clé EXTENSE. Des propriétés et des méthodes peuvent être ajoutées, supprimées ou modifiées au besoin pour créer des objets humains plus faciles et plus clairs:

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  speak() {
    console.log(`${this.name} says "${this.noise}"`);
  }

  walk() {
    console.log(`${this.name} walks on ${this.legs} legs`);
  }

}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Super fait référence à la classe parent, c'est donc généralement le premier appel appelé dans le constructeur. Dans cet exemple, la méthode Human Speak () remplace la méthode définie dans l'animal. Vous pouvez maintenant créer une instance d'objet humain:

let rex = new Animal('Rex', 4, 'woof');
rex.speak();          // Rex says "woof"
rex.noise = 'growl';
rex.speak();          // Rex says "growl"
Copier après la connexion
Copier après la connexion

Méthodes et propriétés statiques

La définition de méthodes utilisant des mots clés statiques permet de l'appeler sur une classe sans créer une instance d'objet. Considérez les constantes math.pi: il n'est pas nécessaire de créer un objet mathématique avant d'accéder aux propriétés PI. ES6 ne prend pas en charge les mêmes propriétés statiques que les autres langues, mais les propriétés peuvent être ajoutées à la définition de classe elle-même. Par exemple, la classe humaine peut être adaptée pour maintenir le nombre d'objets humains créés:

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  speak() {
    console.log(`${this.name} says "${this.noise}"`);
  }

  walk() {
    console.log(`${this.name} walks on ${this.legs} legs`);
  }

  // setter
  set eats(food) {
    this.food = food;
  }

  // getter
  get dinner() {
    return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
  }

}

let rex = new Animal('Rex', 4, 'woof');
rex.eats = 'anything';
console.log( rex.dinner );  // Rex eats anything for dinner.
Copier après la connexion
Copier après la connexion
Le Getter statique de la classe

renverra le nombre d'humains en conséquence:

class Human extends Animal {

  constructor(name) {

    // 调用Animal构造函数
    super(name, 2, 'nothing of interest');
    this.type = 'human';

  }

  // 重写Animal.speak
  speak(to) {

    super.speak();
    if (to) console.log(`to ${to}`);

  }

}
Copier après la connexion

ES2019 Fields de classe ( new )

La nouvelle implémentation du champ de classe permet l'initialisation des propriétés publiques en dehors de tout constructeur en haut de la classe:

let don = new Human('Don');
don.speak('anyone');        // Don says "nothing of interest" to anyone

don.eats = 'burgers';
console.log( don.dinner );  // Don eats burgers for dinner.
Copier après la connexion

Cela équivaut à:

class Human extends Animal {

  constructor(name) {

    // 调用Animal构造函数
    super(name, 2, 'nothing of interest');
    this.type = 'human';

    // 更新Human对象的计数
    Human.count++;

  }

  // 重写Animal.speak
  speak(to) {

    super.speak();
    if (to) console.log(`to ${to}`);

  }

  // 返回人类对象的个数
  static get COUNT() {
    return Human.count;
  }

}

// 类的静态属性本身 - 不是其对象
Human.count = 0;
Copier après la connexion

Si vous avez toujours besoin du constructeur, l'initialisateur sera exécuté avant son exécution.

champ de classe statique

Dans l'exemple ci-dessus, des propriétés statiques sont ajoutées à l'objet de définition de classe de manière inélégante après avoir défini l'objet de classe. Vous n'avez pas besoin d'utiliser des champs de classe:

console.log(`Humans defined: ${Human.COUNT}`); // Humans defined: 0

let don = new Human('Don');

console.log(`Humans defined: ${Human.COUNT}`); // Humans defined: 1

let kim = new Human('Kim');

console.log(`Humans defined: ${Human.COUNT}`); // Humans defined: 2
Copier après la connexion

Cela équivaut à:

class MyClass {

  a = 1;
  b = 2;
  c = 3;

}
Copier après la connexion

Champ de classe privée

Tous les attributs de la classe

ES6 sont publics par défaut et peuvent être vérifiés ou modifiés en dehors de la classe . Dans l'exemple d'animal ci-dessus, rien ne peut empêcher de modifier la propriété alimentaire sans appeler le setter à manger:

class MyClass {

  constructor() {
    this.a = 1;
    this.b = 2;
    this.c = 3;
  }

}
Copier après la connexion
D'autres langues permettent généralement la déclaration d'attributs privés. Ce n'est pas possible dans ES6, donc les développeurs utilisent souvent des conventions de soulignement (_propertyName), des fermetures, des symboles ou des maps faibles pour résoudre ce problème. Le soulignement donne aux développeurs un indice, mais rien ne peut les empêcher d'accéder à la propriété. Dans ES2019, les champs de classe privée sont définis à l'aide de Hash # Prefix:

class MyClass {

  x = 1;
  y = 2;
  static z = 3;

}

console.log( MyClass.z ); // 3
Copier après la connexion
Veuillez noter que les méthodes privées, les getters ou les setters ne peuvent pas être définis. TC39 Phase 3: Draft Proposition recommande l'utilisation d'un préfixe de hachage # pour les noms, qui est implémenté dans Babel. Par exemple:

class MyClass {

  constructor() {
    this.x = 1;
    this.y = 2;
  }

}

MyClass.z = 3;

console.log( MyClass.z ); // 3
Copier après la connexion

Bénéfice immédiatement: Code de réaction plus concis!

Les composants réagis ont généralement des méthodes liées aux événements DOM. Pour s'assurer que cela se résout en composant, il est nécessaire de lier chaque méthode en conséquence. Par exemple:

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  set eats(food) {
    this.food = food;
  }

  get dinner() {
    return `${this.name} eats ${this.food || 'nothing'} for dinner.`;
  }

}

let rex = new Animal('Rex', 4, 'woof');
rex.eats = 'anything';      // 标准setter
rex.food = 'tofu';          // 完全绕过eats setter
console.log( rex.dinner );  // Rex eats tofu for dinner.
Copier après la connexion
Lorsqu'il est défini comme un champ de classe ES2019, il peut être attribué en fonction à l'aide de la flèche ES6 = & gt; qui est automatiquement liée à l'objet de définition. Pas besoin d'ajouter une instruction de liaison:

class MyClass {

  a = 1;          // .a是公共的
  #b = 2;         // .#b是私有的
  static #c = 3;  // .#c是私有的和静态的

  incB() {
    this.#b++;
  }

}

let m = new MyClass();

m.incB(); // 运行正常
m.#b = 0; // 错误 - 私有属性不能在类外部修改
Copier après la connexion

Champ de classe: amélioré?

La définition de la classe ES6 est trop simple. Les champs de classe ES2019 nécessitent moins de code, améliorent la lisibilité et implémentent certaines possibilités intéressantes pour la programmation orientée objet. Utiliser # signifie la privatin a reçu des critiques, principalement parce qu'elle est laide et ressemble à une compétence. La plupart des langues implémentent le mot-clé privé, donc essayer d'utiliser ce membre en dehors de la classe sera rejeté par le compilateur. JavaScript est interprété. Considérez le code suivant:

class Animal {

  constructor(name = 'anonymous', legs = 4, noise = 'nothing') {

    this.type = 'animal';
    this.name = name;
    this.legs = legs;
    this.noise = noise;

  }

  speak() {
    console.log(`${this.name} says "${this.noise}"`);
  }

  walk() {
    console.log(`${this.name} walks on ${this.legs} legs`);
  }

}
Copier après la connexion
Copier après la connexion
Copier après la connexion

Cela lancera une erreur d'exécution sur la dernière ligne, mais ce n'est qu'une grave conséquence d'essayer de définir la propriété. JavaScript est délibérément tolérant et ES5 permet de modifier les propriétés sur n'importe quel objet. Bien que maladroit, le symbole # est invalide en dehors de la définition de la classe. Essayer d'accéder à MyObject. # Secret peut lancer une erreur de syntaxe. Ce débat se poursuivra, mais les champs de classe sont déjà adoptés dans plusieurs moteurs JavaScript, comme cela. Ils continueront d'exister.

FAQS (FAQ) sur les champs de classe privée JavaScript

Quels sont les avantages de l'utilisation de champs de classe privée JavaScript?

Les champs de classe privée en JavaScript fournissent un moyen d'encapsuler ou de masquer des données dans une classe, qui est le principe de base de la programmation orientée objet. Cette encapsulation garantit que l'état interne d'un objet ne peut être modifié que par une classe explicitement définie. Cela rend le code plus robuste et prévisible car il empêche le code externe de modifier accidentellement l'état de l'objet d'une manière inattendue. De plus, les champs privés peuvent aider à simplifier l'interface des classes car elles réduisent le nombre de propriétés et de méthodes exposées au monde extérieur.

Comment déclarer les champs de classe privée en JavaScript?

Dans JavaScript, les champs de classe privée sont déclarés en ajoutant un symbole de hachage (#) avant le nom du champ. Par exemple, pour déclarer un champ privé nommé "valeur" dans une classe, vous pouvez écrire un #Value. Ce champ ne peut ensuite être accessible que dans les méthodes internes de la classe, et non de l'extérieur de la classe.

Puis-je accéder aux champs de classe privée de l'extérieur de la classe?

Non, les champs de classe privée en JavaScript ne sont pas accessibles à partir de l'extérieur de la classe. C'est par conception, car l'une des principales utilisations des champs privés est de masquer les données internes du monde extérieur. Si vous essayez d'accéder à un champ privé depuis l'extérieur de la classe, JavaScript lancera une erreur de syntaxe.

Puis-je utiliser des champs de classe privée avec des domaines publics?

Oui, les classes JavaScript peuvent avoir des domaines privés et publics. Les domaines publics sont déclarés de la même manière que les champs privés, mais n'ont pas de préfixe de hachage (#). Contrairement aux champs privés qui ne sont accessibles qu'à l'intérieur d'une classe, les champs publics sont accessibles et modifiés à l'intérieur et à l'extérieur de la classe.

En quoi les champs de classe privée sont-ils différents des méthodes privées en JavaScript?

Les champs de classe privée et les méthodes privées en JavaScript ont des utilisations similaires, qui fournissent tous deux un moyen de masquer les détails internes d'une classe du monde extérieur. Cependant, ils sont utilisés différemment. Les champs privés sont utilisés pour stocker des données qui ne peuvent être accessibles que dans la classe, tandis que les méthodes privées sont des fonctions qui ne peuvent être appelées qu'à l'intérieur de la classe.

Puis-je utiliser des champs de classe privée dans tous les environnements JavaScript?

Les champs de classe privée sont des fonctionnalités relativement nouvelles en JavaScript, donc tous les environnements ne le prennent pas en charge. Au moment de la rédaction du moment de la rédaction, les dernières versions de la plupart des navigateurs majeurs, notamment Chrome, Firefox et Safari, prennent en charge les champs privés. Cependant, Internet Explorer ne les soutient pas. Si vous devez écrire du code qui s'exécute dans tous les navigateurs, vous devrez peut-être utiliser un convertisseur comme Babel pour convertir le code en un formulaire que les navigateurs plus anciens peuvent comprendre.

Comment utiliser des champs de classe privée dans les méthodes intérieures d'une classe?

Pour utiliser un champ de classe privée dans une méthode interne d'une classe, reportez-vous simplement au champ avec son nom (préfixé avec un symbole de hachage (#)). Par exemple, si vous avez un champ privé appelé "valeur", vous pouvez y accéder dans votre méthode comme ceci: ce. # Valeur.

Puis-je utiliser des champs de classe privée en sous-classes?

Oui, les champs de classe privée peuvent être utilisés dans les sous-classes de JavaScript. Cependant, chaque sous-classe a son propre ensemble indépendant de champs privés qui ne sont pas partagés avec des superclasses ou d'autres sous-classes. Cela signifie que si le champ privé déclaré par la sous-classe est du même nom que le champ privé de la superclasse, les deux champs sont complètement indépendants et n'interfèrent pas les uns avec les autres.

Puis-je utiliser des champs de classe privée dans des méthodes statiques?

Non, les champs de classe privée en JavaScript ne peuvent pas être utilisés dans les méthodes statiques. En effet, les méthodes statiques sont associées à la classe elle-même, et non aux instances de la classe, et les champs privés ne sont accessibles que dans les cas de la classe.

Puis-je itérer sur des champs de classe privée en JavaScript?

Non, les champs de classe privée en JavaScript ne sont pas inclus dans l'itération de la propriété de l'objet. C'est par conception, car l'une des principales utilisations des champs privés est de masquer les données internes du monde extérieur. Si vous avez besoin d'itérer les propriétés de l'objet, vous devez utiliser un champ ou une méthode public à la place.

Cette réponse maintient le format d'image d'origine et le placement, et paraphrase le texte tout en préservant la signification d'origine.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal