[ Web Proxy ]
URL:
Viewing: https://developer.mozilla.org/fr/docs/Web/JavaScript/Reference/Classes/Public_class_fields [Back]  [Original]

Champs de classe publics - JavaScript | MDN

Cette page a t traduite partir de l'anglais par la communaut. Vous pouvez contribuer en rejoignant la communaut francophone sur MDN Web Docs.

View in English Always switch to English

Champs de classe publics

Baseline
Large disponibilit

Cette fonctionnalit est bien tablie et fonctionne sur de nombreux appareils et versions de navigateurs. Elle est disponible sur tous les navigateurs depuis septembre 2022.

Les champs publics sont des proprits qui peuvent tre crites, numres et configures, dfinies sur chaque instance de classe ou constructeur de classe.

Dans cet article

Syntaxe

js
class ClassWithField {
  instanceField;
  instanceFieldWithInitializer = "instance field";
  static staticField;
  static staticFieldWithInitializer = "static field";
}

Il existe quelques restrictions supplmentaires de syntaxe :

  • Le nom d'une proprit statique (champ ou mthode) ne peut pas tre prototype.
  • Le nom d'un champ de classe (statique ou d'instance) ne peut pas tre constructor.

Description

Cette page prsente en dtail les champs d'instance publics.

Les champs d'instance publics existent sur chaque instance cre d'une classe. En dclarant un champ public, vous pouvez vous assurer que le champ est toujours prsent, et la dfinition de la classe est plus auto-documente.

Les champs d'instance publics sont ajouts l'instance soit au moment de la construction dans la classe de base (avant l'excution du corps du constructeur), soit juste aprs le retour de super() dans une sous-classe. Les champs sans initialisation sont initialiss undefined. Comme les proprits, les noms de champs peuvent tre calculs.

js
const PREFIX = "prefixe";

class ClasseAvecChamps {
  champ;
  champInitialise = "champ d'instance";
  [`${PREFIX}DuChamp`] = "champ prfix";
}

const instance = new ClasseAvecChamps();
console.log(Object.hasOwn(instance, "champ")); // true
console.log(instance.champ); // undefined
console.log(instance.champInitialise); // "champ d'instance"
console.log(instance.prefixeDuChamp); // "champ prfix"

Les noms de champs calculs ne sont valus qu'une seule fois, au moment de la dfinition de la classe. Cela signifie que chaque classe a toujours un ensemble fixe de noms de champs, et que deux instances ne peuvent pas avoir des noms de champs diffrents avec des noms calculs. La valeur de this dans l'expression calcule est le this entourant la dfinition de la classe, et se rfrer au nom de la classe est une ReferenceError, car la classe n'est pas encore initialise. await et yield fonctionnent comme prvu dans cette expression.

js
class C {
  [Math.random()] = 1;
}

console.log(new C());
console.log(new C());
// Les deux instances ont le mme nom de champ

Dans l'initialisation du champ, this fait rfrence l'instance de la classe en cours de construction, et super fait rfrence la proprit prototype de la classe de base, qui contient les mthodes d'instance de la classe de base, mais pas ses champs d'instance.

js
class Base {
  champBase = "champ de base";
  autreChampDeBase = this.champBase;
  methodeBase() {
    return "retour de la mthode de base";
  }
}

class Derivee extends Base {
  sousChamp = super.methodeBase();
}

const base = new Base();
const sous = new Derivee();

console.log(base.autreChampDeBase); // "champ de base"

console.log(sous.sousChamp); // "retour de la mthode de base"

L'expression d'initialisation du champ est value chaque fois qu'une nouvelle instance est cre. (Comme la valeur de this est diffrente pour chaque instance, l'expression d'initialisation peut accder aux proprits spcifiques l'instance.)

js
class C {
  obj = {};
}

const instance1 = new C();
const instance2 = new C();
console.log(instance1.obj === instance2.obj); // false

L'expression est value de manire synchrone. Vous ne pouvez pas utiliser await ou yield dans l'expression d'initialisation. (Pensez l'expression d'initialisation comme tant implicitement enveloppe dans une fonction.)

Comme les champs d'instance d'une classe sont ajouts avant l'excution du constructeur respectif, vous pouvez accder aux valeurs des champs dans le constructeur. Cependant, comme les champs d'instance d'une classe drive sont dfinis aprs le retour de super(), le constructeur de la classe de base n'a pas accs aux champs de la classe drive.

js
class Base {
  constructor() {
    console.log("Constructeur de base :", this.champ);
  }
}

class Derivee extends Base {
  champ = 1;
  constructor() {
    super();
    console.log("Constructeur driv :", this.champ);
    this.champ = 2;
  }
}

const instance = new Derivee();
// Constructeur de base : undefined
// Constructeur driv : 1
console.log(instance.champ); // 2

Les champs sont ajouts un par un. Les initialisations de champs peuvent faire rfrence aux valeurs des champs situs au-dessus, mais pas en dessous. Toutes les mthodes d'instance et statiques sont ajoutes au pralable et peuvent tre accessibles, bien que les appeler puisse ne pas se comporter comme prvu si elles font rfrence des champs situs en dessous.

js
class C {
  a = 1;
  b = this.c;
  c = this.a + 1;
  d = this.c + 1;
}

const instance = new C();
console.log(instance.d); // 3
console.log(instance.b); // undefined

Note : C'est encore plus important avec les champs privs, car accder un champ priv non initialis dclenche une TypeError, mme si le champ priv est dclar en dessous. (Si le champ priv n'est pas dclar, cela provoque une SyntaxError prcoce.)

Comme les champs de classe sont ajouts en utilisant la smantique [[DefineOwnProperty]] (qui est essentiellement Object.defineProperty()), les dclarations de champs dans les classes drives n'invoquent pas les accesseurs dans la classe de base. Ce comportement diffre de l'utilisation de this.champ = dans le constructeur.

js
class Base {
  set champ(val) {
    console.log(val);
  }
}

class DeriveeAvecChamp extends Base {
  champ = 1;
}

const instance = new DeriveeAvecChamp(); // Pas de journalisation

class DeriveeAvecConstructeur extends Base {
  constructor() {
    super();
    this.champ = 1;
  }
}

const instance2 = new DeriveeAvecConstructeur(); // Journalise 1

Note : Avant que la spcification des champs de classe ne soit finalise avec la smantique [[DefineOwnProperty]], la plupart des transpileurs, y compris Babel (angl.) et tsc (angl.), transformaient les champs de classe en la forme DeriveeAvecConstructeur, ce qui a caus des bogues subtils aprs la standardisation des champs de classe.

Exemples

Utiliser des champs de classe

Les champs de classe ne peuvent pas dpendre des arguments du constructeur, donc les initialisations de champs valuent gnralement la mme valeur pour chaque instance ( moins que la mme expression puisse valuer des valeurs diffrentes chaque fois, comme Math.random() ou les initialisations d'objets).

js
class Personne {
  nom = argNom; // argNom est hors de la porte du constructeur
  constructor(argNom) {}
}
js
class Personne {
  // Toutes les instances de Personne ont le mme nom
  nom = "Dragomir";
}

Cependant, mme dclarer un champ de classe vide est bnfique, car cela indique l'existence du champ, ce qui permet aux vrificateurs de type ainsi qu'aux lecteurices humaines d'analyser statiquement la structure de la classe.

js
class Personne {
  nom;
  age;
  constructor(nom, age) {
    this.nom = nom;
    this.age = age;
  }
}

Le code ci-dessus semble rptitif, mais considrez le cas o this est mut dynamiquement : la dclaration explicite du champ permet de savoir quels champs sont dfinitivement prsents sur l'instance.

js
class Personne {
  nom;
  age;
  constructor(proprietes) {
    Object.assign(this, proprietes);
  }
}

Comme les initialisations sont values aprs l'excution de la classe de base, vous pouvez accder aux proprits cres par le constructeur de la classe de base.

js
class Personne {
  nom;
  age;
  constructor(nom, age) {
    this.nom = nom;
    this.age = age;
  }
}

class Professeur extends Personne {
  nom = `Professeur ${this.nom}`;
}

console.log(new Professeur("Radev", 54).nom); // "Professeur Radev"

Spcifications

Spcification
ECMAScript 2027 LanguageSpecification
# prod-FieldDefinition

Compatibilit des navigateurs

Voir aussi


Web Proxy Viewer  |  New URL  |  Original Page