JavaScript имеет наследование прототипа. Объекты могут наследовать другие объекты. В основном это означает, что вы можете «видеть» свойства родительского объекта¹ на дочернем:
const parent = { inherited: true };
const child = Object.create(parent);
child.inherited // true
Конструкторы - это просто функции, чье свойство .prototype
представляет объект, от которого наследуются экземпляры:
const foo = new Foo();
// equals
const foo = Object.create(Foo.prototype);
Foo.call(foo); // execute the constructor with "this" being "foo"
Точно так же instanceof
- это просто механизм в цепочке прототипов: он проверяет, находятся ли функции .prototype
внутри родительской цепочки объектов.
Цепочка? Да, объекты, чей родитель также имеет родителя, также наследуют свойства родительского родителя. Таким образом, чтобы создать «класс», который наследует другой «класс», мы должны установить родительские классы .prototype
для суперклассов .prototype
. Это можно сделать с помощью
Bar.prototype = new Foo();
, поскольку new Foo
возвращает объект, чей родитель Foo.prototype
, поэтому экземпляры Bar наследуют Bar.prototype
, который наследует Foo.prototype
.
Parent «Родительский объект» официально называется «прототип объекта», я попытался избежать возможной путаницы между прототипом объекта и свойством прототипа объекта функции
Хотя этот метод работает, вы также выполнить конструктор Foo
для чего-то, что на самом деле не является экземпляром (технически да, но не концептуально). Есть (лучшие) альтернативы, например, создание экземпляра без выполнения конструктора:
Bar.prototype = Object.create(Foo.prototype);
или непосредственная установка родительского объекта:
Object.setPrototypeOf(Bar.prototype, Foo.prototype);
Или, если вы используете синтаксис class
:
class Bar extends Foo {
//...
}