Skip to main content

Наследование

Пример до классов JS

До введения синтаксиса классов в ECMAScript 6 (ES6), наследование в JavaScript осуществлялось с использованием функций-конструкторов и прототипов.

// Родительский класс Person1
function Person1(name, age) {
this.name = name;
this.age = age;
}

Person1.prototype.describe = function () {
return `${this.name}, ${this.age} years old`;
};

// Дочерний класс Employee
function Employee(name, age, jobTitle) {
Person1.call(this, name, age); // Вызов конструктора родительского класса
this.jobTitle = jobTitle;
}

// Наследование от Person1
Employee.prototype = Object.create(Person1.prototype);
Employee.prototype.constructor = Employee;

// Добавление метода к прототипу Employee
Employee.prototype.describeJob = function () {
return `${this.name}, ${this.age} years old, ${this.jobTitle}`;
};

var john = new Person1("John", 30);
console.log(john.describe()); // "John, 30 years old"

var jane = new Employee("Jane", 25, "Software Engineer");
console.log(jane.describe()); // "Jane, 25 years old"
console.log(jane.describeJob()); // "Jane, 25 years old, Software Engineer"

В этом примере:

  • Person1 — это функция-конструктор, представляющая родительский класс.
  • Employee — это функция-конструктор, представляющая дочерний класс.
  • Employee.prototype = Object.create(Person1.prototype); устанавливает прототип Employee на экземпляр Person1, что позволяет Employee наследовать методы и свойства Person1.
  • Employee.prototype.constructor = Employee; устанавливает конструктор Employee на сам Employee, чтобы методы наследования инициализировались правильно.
  • Метод describeJob добавляется к прототипу Employee, чтобы расширить функциональность родительского класса Person1.

Этот подход позволяет создавать объекты Employee, которые наследуют свойства и методы от Person1, а также добавлять свои собственные.

Пример на классах JS

// Родительский класс Person1
class Person1 {
constructor(name, age) {
this.name = name;
this.age = age;
}

describe() {
return `${this.name}, ${this.age} years old`;
}
}

// Дочерний класс Employee
class Employee extends Person1 {
constructor(name, age, jobTitle) {
super(name, age); // Вызов конструктора родительского класса
this.jobTitle = jobTitle;
}

describeJob() {
return `${this.name}, ${this.age} years old, ${this.jobTitle}`;
}
}

const john = new Person1("John", 30);
console.log(john.describe()); // "John, 30 years old"

const jane = new Employee("Jane", 25, "Software Engineer");
console.log(jane.describe()); // "Jane, 25 years old"
console.log(jane.describeJob()); // "Jane, 25 years old, Software Engineer"

В этом примере:

  • class Person1 — это родительский класс.
  • Конструктор constructor(name, age) и метод describe() определены внутри класса Person1.
  • class Employee extends Person1 — это дочерний класс, который наследует от Person1.
  • Внутри конструктора дочернего класса Employee используется super(name, age) для вызова конструктора родительского класса.
  • Метод describeJob() добавляется непосредственно в класс Employee.

Этот подход позволяет создавать объекты Employee, которые наследуют свойства и методы от Person1, а также добавлять свои собственные методы и свойства.

Описание ключевого слова this

function Person1(name, age) {
this.name = name;
this.age = age;
}

В функции-конструкторе Person1, ключевое слово this используется для создания свойств name и age, которые будут принадлежать каждому экземпляру, созданному с помощью этого конструктора. Когда вы создаете новый объект с помощью new Person1(name, age), this ссылается на вновь созданный объект.

Person1.prototype.describe = function () {
return `${this.name}, ${this.age} years old`;
};

В методе describe, добавленном к прототипу Person1, ключевое слово this ссылается на экземпляр объекта Person1, который вызывает этот метод. Это позволяет методу describe получить доступ к свойствам name и age конкретного экземпляра.

class Person1 {
constructor(name, age) {
this.name = name;
this.age = age;
}

describe() {
return `${this.name}, ${this.age} years old`;
}
}

В классе Person1 ключевое слово this внутри конструктора constructor(name, age) используется аналогично: для создания свойств name и age, которые будут принадлежать каждому экземпляру, созданному с помощью этого класса. В методе describe ключевое слово this ссылается на экземпляр класса, который вызывает этот метод.

Разница между prototype и __proto__

В JavaScript, prototype и __proto__ являются фундаментальными частями механизма прототипного наследования, но они служат разным целям и используются по-разному.

prototype

  • Это свойство функции-конструктора, используемое в JavaScript для установления наследования. Когда создаётся новый объект с помощью конструктора (например, с использованием оператора new), новому объекту устанавливается прототип, указывающий на объект prototype этого конструктора.
  • Когда вы определяете функцию-конструктор, вы можете добавить методы и свойства в объект prototype, который будет делиться между всеми экземплярами объектов, созданных с использованием этого конструктора. Это означает, что все экземпляры будут иметь доступ к методам и свойствам, определённым в prototype их конструктора.

__proto__

  • это свойство каждого объекта в JavaScript, которое является ссылкой на прототип этого объекта (то есть на объект, от которого объект наследует свойства и методы). Это свойство обычно обозначается как внутреннее свойство [[Prototype]] объекта.
  • Свойство __proto__ используется для доступа или изменения прототипа объекта в рантайме. Однако использование __proto__ в современных разработках не рекомендуется из-за его устаревшего статуса и возможных проблем с производительностью. Вместо этого для работы с прототипами объектов рекомендуется использовать методы Object.getPrototypeOf и Object.setPrototypeOf.