Classes

ES6 a introduit le concept de "classes" en JavaScript, qui diffère des classes des autres langages de programmation. Ici, les classes sont des fonctions spéciales qui servent de modèles pour créer des objets contenant déjà des données, les propriétés associées à ces données et les méthodes liées à la manipulation de ces données. Ces objets, propriétés et méthodes sont collectivement appelés "membres" de la classe.

Pour définir une classe, utilisez le mot clé class. Conformément aux bonnes pratiques et à la convention établie par les fonctions de constructeur intégrées à JavaScript, commencez n'importe quel identifiant de classe par une lettre majuscule:

class MyClass {}

Les classes sont destinées à fournir des moyens plus accessibles d'utiliser les fonctionnalités avancées des prototypes et des fonctions de constructeur:

class MyClass {}

typeof MyClass;
> "function"

Étant donné que les classes ont été en partie ajoutées pour rendre l'utilisation des fonctionnalités JavaScript avancées plus facile et plus attrayante, elles sont parfois appelées sucre syntaxique. Cependant, les classes ne se contentent pas de fournir un raccourci utile pour travailler avec l'héritage prototypique. L'introduction de la syntaxe de classe permet de résoudre des problèmes de conception de longue date dans JavaScript, sans introduire de problèmes de rétrocompatibilité. Par exemple, tout le code dans le corps d'une classe est toujours évalué en mode strict.

Pour créer une instance d'une classe, utilisez l'opérateur new.

class MyClass {}

const myClassInstance = new MyClass();

myClassInstance;
> Object { }

Les fonctions définies dans le corps d'une classe sont exposées en tant que méthodes de chaque instance de cette classe.

class MyClass {
    classMethod() {
        console.log( "My class method." );
    }
}

const myClassInstance = new MyClass();

myClassInstance.classMethod();
> "My class method."

Une méthode définie dans une classe devient une méthode sur le prototype de l'instance résultante. En raison de la nature de la chaîne de prototype, vous pouvez appeler ces méthodes directement sur l'objet obtenu:

class MyClass {
  classMethod() {
    console.log( "My class method." );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { }
    <prototype>: Object { … }
        classMethod: function classMethod()
        constructor: class MyClass { constructor(myPassedValue) }
        <prototype>: Object { … }

myClassInstance.classMethod();
> "My class method."

La création d'une instance de classe appelle une méthode constructor() spéciale qui effectue toutes les "configurations" nécessaires sur l'instance nouvellement créée et initialise toutes les propriétés qui lui sont associées. Tous les arguments transmis à la classe lors de la création de l'instance sont disponibles pour la méthode constructor():

class MyClass {
  constructor( myPassedValue ) {
    console.log( myPassedValue );
  }
}

const myClassInstance = new MyClass( "A string." );
> "A string."

Dans le corps d'une classe, la valeur de this fait référence à l'instance elle-même, et toutes les propriétés définies dans this sont exposées en tant que propriétés de chaque instance de cette classe:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProperty = myPassedValue;
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance;
> Object { instanceProperty: "A string." }

Ces propriétés sont également disponibles pour toutes les méthodes dans le corps de la classe:

class MyClass {
  constructor( myPassedValue ) {
    this.instanceProp = myPassedValue;
  }
  myMethod() {
    console.log( this.instanceProp );
  }
}

const myClassInstance = new MyClass( "A string." );

myClassInstance.myMethod();
> "A string."

Si vous ne définissez pas de constructor() pour votre classe, le moteur JavaScript suppose une valeur constructor "par défaut" vide. Chaque classe ne peut avoir qu'une seule méthode spéciale nommée constructor():

class MyClass {
  constructor() {}
  constructor() {}
}
> Uncaught SyntaxError: A class may only have one constructor

Vous pouvez définir une classe à l'aide d'une déclaration de classe ou d'une expression de classe. Les exemples précédents étaient tous des déclarations de classe, qui exigent que les noms soient appelés à l'aide de new. Les expressions de classe peuvent être nommées ou non nommées pour créer une classe "anonyme".

let ClassExpression = class {
    constructor() {}
};

ClassExpression;
> class  {}

Vous pouvez utiliser des expressions de classe anonymes pour les fonctions qui construisent des classes "à la volée" :

function classMaker() {
  return class {
    constructor() {}
  };
}

let MyVariable = classMaker();

MyVariable;
> class  {}

Le fait de redéclarer une classe à l'aide d'une déclaration de classe entraîne une erreur de syntaxe:


class MyClass {
    constructor( ) {
        console.log( "My class." );
    }
};

class MyClass {
    constructor() {
        console.log( "My new class." );
    }
};
> Uncaught SyntaxError: redeclaration of class MyClass

Cependant, les expressions de classe vous permettent de redéfinir une classe:

let ClassExpression = class MyClass { };

ClassExpression = class MyOtherClass {
    constructor( myString ) {
        this.myProp = myString;
    }
};

new ClassExpression( "String." );
> MyOtherClass {myProp: 'String.'}

Vous ne pouvez pas appeler une expression de classe nommée par son nom comme une déclaration de classe. Toutefois, le nom attribué à une expression de classe est disponible en tant que propriété de l'instance créée, principalement pour faciliter le débogage:

let MyVariable = class MyClass {};

MyClass;
> Uncaught ReferenceError: MyClass is not defined

MyVariable;
> class MyClass {}

MyVariable.name;
> "MyClass"

Lorsque vous initialisez une variable à l'aide d'une expression de classe, les règles de hissage de cette variable sont suivies comme prévu. Les déclarations de classe suivent les mêmes règles de "zone morte temporelle" que let et const, et se comportent comme si elles n'avaient pas été hissées en haut de leur champ d'application actuel, ce qui signifie que l'appel d'une classe avant la déclaration de classe entraîne une erreur:

{
    let myVar = new MyClass( "Property string." );

    class MyClass {
        myProp;

        constructor( myString ) {
            this.myProp = myString;
        }
    };
};
> Uncaught ReferenceError: Cannot access 'MyClass' before initialization

Testez vos connaissances

Parmi les énoncés suivants, lequel définit correctement une classe ?

class MyClass {}
myClass = class {}
new class()

Combien de méthodes constructor() une classe peut-elle comporter ?

Un
Aucun
Illimité