Как перегрузить конструкторы в JavaScript ECMA6?

Цель

Реализовать механизм, разрешающий перегрузку конструктора в JavaScript ECMA6.

Почему это не дубликат

Тема Почему JavaScript ES6 не поддерживает классы с несколькими конструкторами?, хотя подобный не такой, как этот. В другом разделе рассматривается только перегрузка конструктора с использованием старых версий ECMAScript, а в этом разделе рассматривается ECMA6. Если вы ищете обновленный ответ, это место.

Фон

У меня есть класс JavaScript с заданным конструктором, и я хочу, чтобы пользователь мог иметь разные конструкторы при создании экземпляра объекта. Примером того, что я притворяюсь, может быть следующее:

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);
    }
}

В этом коде у пользователя есть три конструктора, которые он может использовать, каждый из которых принимает разное количество параметров. Ниже приведен пример использования:

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

Проблема

Это простой пример, если вы используете Java или C#, потому что эти языки имеют перегрузки конструктора.

Однако из документации по классам из MDN можно сделать вывод, что JavaScript нет.

Вопрос

  1. Есть ли способ реализовать аналогичный механизм для классов JavaScript с помощью ECMA6? Если нет, то какая лучшая/ближайшая альтернатива?

person Flame_Phoenix    schedule 07.07.2016    source источник
comment
Взгляните на этот очень похожий вопрос: Почему JavaScript ES6 не имеет класс с несколькими конструкторами?   -  person oberbics    schedule 07.07.2016
comment
Я думаю, что конечная проблема заключается в том, что Javascript просто не является Java, и имитация идиом Java приводит к большому количеству проблем в целом. Это только мое мнение.   -  person    schedule 07.07.2016
comment
Отличный вопрос, если вы действительно думаете, что перегрузка — это хорошая идея. Ваш пример кричит Строитель.   -  person a better oliver    schedule 07.07.2016
comment
@zeroflagL: возможно, вы не могли бы дать ответ с примером? Я фанат узоров!   -  person Flame_Phoenix    schedule 07.07.2016
comment
Взгляните на TypeScript. Они используют типизированные объекты, такие как object: int   -  person Soldeplata Saketos    schedule 07.07.2016
comment
как насчет использования typeof ??   -  person Soldeplata Saketos    schedule 07.07.2016


Ответы (2)


В JavaScript нет встроенного решения для этого. Альтернативным решением может быть использование объекта arguments (в некоторых случаях) или передача собственных параметров конфигурации, например:

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;
    }
}

В основном это решение старой школы, я использую ту же логику в ES3.

person meskobalazs    schedule 07.07.2016
comment
Вместо объекта arguments вы можете использовать ...restParameters, что дает вам настоящий массив. - person gcampbell; 07.07.2016
comment
При использовании оператора || сначала следует указать параметр options, иначе вы всегда будете получать объект по умолчанию. - person Soldeplata Saketos; 07.07.2016
comment
упс, правда :) обновил, спасибо - person meskobalazs; 07.07.2016

Вы правы (насколько я знаю), что это не поддержка классов JavaScript. Моя рекомендация здесь, поскольку вы уже используете функции ES6, будет заключаться в использовании параметры по умолчанию вместо этого:

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

Это, очевидно, связано с оговоркой, что у вас не может быть "перегрузок" с разными порядками параметров, как в вашем примере (хотя, на мой взгляд, это хорошо - с согласованным API гораздо приятнее работать).

ответ meskobalazs также является хорошим вариантом, особенно если у вас есть много опций, которые вы хотите, чтобы ваш объект принимал. Выполнение этого с помощью таких параметров функции может стать немного запутанным!

person Joe Clay    schedule 07.07.2016