2016-03-28 5 views
0

Теперь, когда JavaScript имеет классы, мне интересно, как можно вызвать супер-конструктор вне конструктора класса.Как вызвать супер конструктор вне конструктора?

Моя неудачная попытка наивны (результаты в SyntaxError):

class A 
{ 
    constructor() { this.a = 1; } 
} 

function initB() 
{ 
    super(); // How to invoke new A() on this here? 
    this.b = 2; 
} 

class B extends A 
{ 
    constructor() { initB.call(this); } 
} 

Я знаю, что в каком-то другом языке, как Java супер конструктор может быть вызван только внутри конструктора производного класса, но ES6 классы - это синтаксический сахар для наследования на основе прототипов, поэтому я был бы удивлен, если бы это было невозможно с использованием встроенных функций языка. Я просто не могу понять правильный синтаксис.

Лучшего, что я пришел с до сих пор чувствует себя ужасно, как обман:

class A 
{ 
    constructor() { this.a = 1; } 
} 

function initB() 
{ 
    let newThis = new A(); 
    newThis.b = 2; 
    return newThis; 
} 

class B extends A 
{ 
    constructor() { return initB(); } 
} 
+1

Что мешает вам использовать стандартный класс B extends A {constructor() {super(); this.b = 2; }} ', как это должно быть? – Bergi

+0

Ваше «решение» на самом деле является синтаксической ошибкой. – Bergi

+0

@Bergi Я знаю, что мой первый подход - синтаксическая ошибка, вот почему я спрашиваю. Я разъяснил свой вопрос, спасибо. –

ответ

6

Каждого конструктор класса, который extends что-то обязательно содержит прямой super(…) вызов.
Прямые super(…) звонки могут быть помещены только в конструкторы. На самом деле этого не происходит.

Вы действительно не должны размещать логику инициализации класса в любом месте, кроме своего конструктора. Прямое и правильное решение не использовать initB вообще:

class A { 
    constructor() { this.a = 1; } 
} 

class B extends A { 
    constructor() { 
     super(); 
     this.b = 2; 
    } 
} 

Тем не менее, есть способ подорвать «super() вызов должен быть в конструкторе» требование. Включение его внутрь функции стрелок также считается! Итак, вы могли бы сделать

class A { 
    constructor() { this.a = 1; } 
} 

function initB(_super) { 
    var b = _super(); 
    b.b = 2; 
} 
class B extends A { 
    constructor() { 
     initB(() => super()); 
    } 
} 

Обещайте мне, чтобы этого не сделать, пожалуйста.

Другой шаблон - не называть super() вообще, который работает до тех пор, пока вы возвращаете объект из конструктора. При этом, вы можете поместить фактическое строительство объекта в другом месте:

class A { 
    constructor() { this.a = 1; } 
} 

function makeB() { 
    var b = Reflect.construct(A, [], B); // call the A constructor with B for the prototype 
    b.b = 2; 
    return b; 
} 
class B extends A { 
    constructor() { 
     return makeB(); 
    } 
} 

Который действительно не намного лучше.

+0

«Ввод его внутрь функции стрелки также считается!» --- Это согласно стандарту? 'const a =() => {super()};' --- этот дурацкий бабелей, но возможность избежать вызова родительского конструктора выглядит деструктивным: -S – zerkms

+2

Чтобы пояснить, вызов 'super' - это только необходимо, если вы хотите использовать 'this'. – Oriol

+0

@Oriol, но как насчет [babel/repl] (https://babeljs.io/repl/#?evaluate=true&presets=es2015%2Creact%2Cstage-2&experimental=true&loose=false&spec=true&playground=true&code=class%20A%20% 7В% 0D% 0A% 20% 20% 20% 20constructor()% 20% 7B% 20this.A% 20% 3D% 201% 3B% 20% 7D% 0D% 0A% 7D% 0D% 0A% 0D% 0Aclass% 20В% 20extends% 20A% 20% 7B% 0D% 0A% 20% 20% 20% 20constructor ()% 20% 7B% 0D% 0A% 20% 20% 20% 20% 20% 20% 20% 20const% 20a% 20% 3D% 20()% 20% 3D% 3E% 20% 7B% 20super()% 20% 7D% 3B% 0D% 0A% 20% 20% 20% 20% 20% 20% 20% 20% 20this.a% 3D% 20this.b% 3B% 0D% 0A% 20% 20% 20% 20% 7D% 0D% 0A% 7D)? – zerkms

Смежные вопросы