Наследование
Пример до классов 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.