Наследование Javascript с параметрами родительского конструктора

1

В настоящее время я пытаюсь создать наследование классов с использованием прототипов в javascript, и я понимаю, как это работает в простом примере ниже.

var Person = function(){
    var name = "Steve";
}

var Employee = function(){
    var company = "Stack Overflow";
}

Employee.prototype = new Person;

var employee1 = new Employee();

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

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    //How can I use initName to set the value in the prototype class?

    var company = initCompany;
}

Employee.prototype = new Person;

var employee1 = new Employee("Bob", "Intel");

Как я могу вызвать конструктор Person с именем? В С# (язык, который мне больше всего нравится), вы просто вызываете базовый конструктор и передаете необходимые параметры, но не похоже, что в javascript есть эквивалентный шаблон.

Для справки, это то, как это могло бы выглядеть в С#:

public class Person
{
    string name;

    public Person(string initName)
    {
        name = initName;
    }
}

public class Employee : Person
{
    string company;

    public Employee(string initName, string initCompany) : base(initName)
    {
        company = initCompany;
    }
}

var employee1 = new Employee("Bob", "Intel");

Отказ от ответственности: как вы можете видеть, я в первую очередь объектно-ориентированный программист, но сейчас я работаю в javascript, поэтому некоторые из моих запросов могут быть нечувствительными с точки зрения javascript, не стесняйтесь оспаривать мои предпосылки по мере необходимости.

Теги:
inheritance
constructor
prototype

2 ответа

1
Лучший ответ

Стандарт ES5 и ниже

В конкретном случае вашего примера ответ headmax делает то, что вам нужно. Однако то, что вы пытаетесь сделать в общем смысле (т.е. Классическое наследование), возможно с С# и другими языками с классическими моделями наследования, но это невозможно в модели прототипа JavaScript. Вероятно, вы можете приблизиться к тому, что используете композицию, например:

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    var innerPerson = new Person(initName);

    var company = initCompany;
}

var employee1 = new Employee("Bob", "Intel");

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

РЕДАКТИРОВАТЬ

Ну, это то, о чем я забыл раньше, но на самом деле вы можете добиться большего количества наследования с помощью call() или apply(). Использование вызова или применения позволяет запускать функцию (включая конструкторы объектов) в указанном контексте, поэтому вы можете запустить родительский конструктор в контексте дочернего элемента, например:

var Person = function(initName){
    var name = initName;
}

var Employee = function(initName, initCompany){
    Person.call(this, initName);
    var innerPerson = new Person(initName);

    var company = initCompany;
}

var employee1 = new Employee("Bob", "Intel");

Однако, если вы хотите иметь доступ к свойству имени внутри конструктора Employee и любых других функций, которые вы определяете внутри Employee, вам нужно будет изменить видимость видимости области от var name =... до this.name =... так что он видится в объеме объекта, который строится (к чему this относится), в отличие от привязки к сфере действия функции конструктора. Для прекрасных примеров всего этого в использовании см. Здесь.

ES6

С принятием ECMAScript 2015 вы можете теперь обернуть определения классов в синтаксическом сахаре, который намного больше похож на классическое наследование. Но вы должны помнить, что это все еще реализовано с прототипическим наследованием под капотом, поэтому вероятно, что что-то вроде композиции или call()/apply() происходит, когда механизм JavaScript фактически выполняет код или транспилер, как Babel, переписывает его.

  • 0
    Ладно, звучит так, будто я просто не смогу делать то, что надеюсь, но спасибо за альтернативный подход к использованию композиции. Мне придется пойти с этим сейчас, если кто-то не даст лучший ответ по линии. Если они этого не сделают, то я отмечу ваш как принятый завтра
  • 0
    Рад, что композиция может помочь, но я обновил ответ, чтобы включить некоторые другие способы, которые могут быть полезны и больше похожи на наследование
Показать ещё 1 комментарий
2

JavaScript имеет реальные классы с ES6. Они не будут работать в старых браузерах (например, Internet Explorer), но вы можете записать это как

class Person {
  constructor(name){
    this.name = name;
  }
}

class Employee extends Person {
  constructor(name, company) {
    super(name);
    this.company = company;
  }
}
  • 0
    Да, я хотел бы просто игнорировать старые браузеры и использовать эту реализацию, но, к сожалению, мне приходится поддерживать более старые версии JS, поэтому я не могу использовать это. Есть ли способ сделать эквивалент этого в более старой версии?
  • 0
    Вы можете посмотреть на repl babel и посмотреть, что они делают. Это не самый красивый, но он определенно делает то, что вы ищете. babeljs.io/repl
Показать ещё 1 комментарий

Ещё вопросы

Сообщество Overcoder
Наверх
Меню