Подтвердить что ты не робот

Понимание наследования прототипов

Я нарисовал следующую картину, демонстрирующую, как объекты наследуются (конструкторы функций отмечены как синие, объекты, созданные из этих конструкторов, помечены как зеленые):

введите описание изображения здесь

Вот код, создающий такую ​​иерархию:

function Figure() {}

function Rect() {}
Rect.prototype = new Figure();

function Square() {}
Square.prototype = new Rect();

function Ellipse() {}
Ellipse.prototype = new Figure();

function Circle() {}
Circle.prototype = new Ellipse();

Теперь я хочу проверить, наследуется ли new Square() от Rect, поэтому я ожидаю, что механизм JavaScript проверяет его:

var s = new Square();
s instanceof Rect // ?

s.__proto__ === Rect.prototype // false
new Rect()      new Figure()

s.__proto__.__proto__ === Rect.prototype // true
new Figure()              new Figure()

Итак s instanceof Rect должен возвращать true. Это ожидается и на самом деле возвращается, если я запускаю код. Но затем я хочу проверить, наследуется ли new Circle() от Rect, поэтому я следую той же логике:

var c = new Circle();
c instanceof Rect // ?

c.__proto__ === Rect.prototype // false
new Ellipse()      new Figure()

c.__proto__.__proto__ === Rect.prototype // true
new Figure()              new Figure()

Итак, использование этой логики проверки c instanceof Rect должно возвращать true, но если я действительно запускаю код, c instanceof Rect возвращает false. Неужели я не понимаю механизм оператора instanceof?

4b9b3361

Ответ 1

Ваша логика правильная, но исходные предположения были немного неправильными. Можно эмулировать регулярное классовое наследование с прототипами.

Чтобы воспроизвести структуру, которую вы нарисовали, я создал следующий код:

function Figure() {}
function Rect() {}
function Square() {}

function Ellipse() {}
function Circle() {}

Ellipse.prototype = Rect.prototype = new Figure();

Square.prototype = new Rect();
Circle.prototype = new Ellipse();

console.log("is Figure: " + (new Circle() instanceof Figure));
console.log("is Ellipse: " + (new Circle() instanceof Ellipse));
console.log("is Rect: " + (new Circle() instanceof Rect));

Ответ 2

Учитывая пример кода в вашем вопросе, c.__proto__.__proto__ === Rect.prototype возвращает false. new Figure вызывается дважды и создает два разных экземпляра Figure.

Различные экземпляры объектов не равны.

function Figure() {}

function Rect() {}
Rect.prototype = new Figure();

function Square() {}
Square.prototype = new Rect();

function Ellipse() {}
Ellipse.prototype = new Figure();

function Circle() {}
Circle.prototype = new Ellipse();

var c = new Circle();

console.log('c instanceof Rect:', c instanceof Rect);

console.log('c.__proto__ === Rect.prototype', c.__proto__ === Rect.prototype);

console.log('c.__proto__.__proto__ === Rect.prototype', c.__proto__.__proto__ === Rect.prototype);

Ответ 3

Тот факт, что круги и квадраты имеют рисунок в своих цепочках прототипов, означает, что c instanceof Figure и s instanceof Figure являются истинными, но каждый из них имеет свой собственный рисунок, потому что new Figure() был вызван дважды. Обратите внимание, что new Figure() != new Figure(), поскольку объекты в Javascript никогда не равны другим объектам. Ниже приведена диаграмма, показывающая, что происходит в вашем коде выше. Вы можете видеть, что в кругах и квадратах каждый имеет отдельный рисунок в своих цепочках прототипов:

введите описание изображения здесь

Обратите внимание, что вы можете немного изменить свой код, чтобы повторно использовать одну фигуру в качестве прототипа как для Rect, так и для Ellipse, что будет соответствовать диаграмме в вашем исходном сообщении и приведет к точному поведению, которое вы ожидаете увидеть:

function Figure() {}
var f = new Figure();

function Rect() {}
Rect.prototype = f;

function Square() {}
Square.prototype = new Rect();

function Ellipse() {}
Ellipse.prototype = f;

function Circle() {}
Circle.prototype = new Ellipse();

console.log( (new Circle) instanceof Rect ); // true