Есть ли какой-либо значимый вариант использования для назначения экземпляра одного функционального объекта атрибуту prototype другого функционального объекта? - PullRequest
2 голосов
/ 17 апреля 2020

Есть ли причина, по которой мне следует назначать новый экземпляр одного объекта-функции атрибуту prototype другого объекта-функции? Будет ли это представлять какой-то механизм наследования?

function Foo() {}
function Bar() {}
new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // false

// assign instance of Foo to Bar.prototype:
Bar.prototype = new Foo();

// that results in: 
new Bar() instanceof Bar; // true
new Bar() instanceof Foo; // true

1 Ответ

2 голосов
/ 17 апреля 2020

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 {
   //...
 }
...