web-dev-qa-db-fra.com

Comment surcharger les constructeurs en JavaScript ECMA6?

Objectif

Implémenter un mécanisme pour permettre la surcharge du constructeur dans JavaScript ECMA6

Pourquoi ce n'est pas un doublon

Le sujet Pourquoi JavaScript ES6 ne prend-il pas en charge les classes multi-constructeurs? , bien que similaire ne soit pas le même que celui-ci. L'autre rubrique se concentre uniquement sur une surcharge de constructeur utilisant les anciennes versions ECMAScript, tandis que cette rubrique se concentre sur ECMA6. Si vous cherchez une réponse mise à jour, c'est l'endroit qu'il vous faut.

Contexte

J'ai une classe JavaScript avec un constructeur donné, et je veux que l'utilisateur puisse avoir différents constructeurs lors de l'instanciation d'un objet. Un exemple de ce que je prétends pourrait être le suivant:

const DEFAULT_WHEEL_NUMBER = 4;
const DEFAULT_COLOR = "black";    
const DEFAULT_NAME = "myCar";

class Car{

    constructor(numberWheels, aName, aColor){
        this.wheelsNum = numberWheels;
        this.name = aName;
        this.color = aColor;
    }

    constructor(aName){
        this(DEFUALT_WHEEL_NUMBER, aName, DEFAULT_COLOR);
    }

    constructor(){
        this(DEFUALT_WHEEL_NUMBER, DEFAULT_NAME, DEFAULT_COLOR);
    }
}

Dans ce code, l'utilisateur a trois constructeurs qu'il peut utiliser, chacun prenant une quantité différente de paramètres. Un exemple d'utilisation suit:

var car1 = new Car(3, "tricicle-car", "white");
var car2 = new Car("Opel"); //creates black car with 4 wheels called Opel
var car3 = new Car(); //creates a black car, with 4 wheels called myCar

Problème

Ceci est un exemple simple si l'on utilise Java ou C #, car ces langages ont des surcharges de constructeur.

Cependant, à partir de la documentation sur les classes de MDN on peut conclure que JavaScript ne fonctionne pas.

Question

  1. Existe-t-il un moyen d'implémenter un mécanisme similaire pour les classes JavaScript à l'aide d'ECMA6? Sinon, quelle est la meilleure alternative/la plus proche?
14
Flame_Phoenix

Il n'y a pas de solution intégrée pour cela en JavaScript. Une solution alternative peut être d'utiliser l'objet arguments (dans certains cas), ou passer vos propres options de configuration, similaire à ceci:

const defaults = {
    numberWheels: 4,
    color: "black",   
    name: "myCar"
}

class Car {
    constructor(options) {
         this.wheelsNum = options.numberWheels || defaults.numberWheels;
         this.name = options.name || defaults.name;
         this.color = options.color || defaults.color;
    }
}

Il s'agit essentiellement de la solution old school, j'utilise la même logique dans ES3.

9
meskobalazs

Vous avez raison (pour autant que je sache) que ce n'est pas une fonctionnalité prise en charge par les classes JavaScript. Ma recommandation ici, puisque vous utilisez déjà les fonctionnalités d'ES6, serait d'utiliser plutôt paramètres par défaut :

class Car {
    constructor(numberWheels = 4, aName = "myCar", aColor = "black"){
        this.wheelsNum = numberWheels;
        this.name = aName;
        this.color = aColor;
    }
}

Cela vient évidemment avec la mise en garde que vous ne pouvez pas avoir de `` surcharges '' avec différents ordres de paramètres comme vous le faites dans votre exemple (bien qu'à mon avis, c'est une bonne chose - une API cohérente est beaucoup plus agréable à travailler).

la réponse de meskobalazs est également une bonne option, surtout si vous avez beaucoup d'options que vous souhaitez que votre objet accepte. Faire cela avec des paramètres de fonction comme celui-ci peut devenir un peu compliqué!

10
Joe Clay