Наследование методов в цепочке прототипов JavaScript

"В javascript каждый объект имеет секретную ссылку на объект, который его создал, образуя цепочку. Когда у объекта запрашивается свойство, которого у него нет, запрашивается его родительский объект... постоянно вверх по цепочке пока свойство не будет найдено или пока не будет достигнут корневой объект."

Все, я всегда думаю, что приведенные выше слова верны даже сейчас, поэтому я провел некоторый тест, чтобы проверить это, я намеревался определить взаимосвязь объектов, как показано ниже. пожалуйста, просмотрите его.

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

Код должен выглядеть так, как показано ниже.

        //Shape - superclass
        function Shape() {
          this.x = 0;
          this.y = 0;
        };

        Shape.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;

            alert('Shape move');
        };

        // Rectangle - subclass
        function Rectangle() {
          Shape.call(this); //call super constructor.
        }

        Rectangle.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;

            alert('Rectangle move');
        };

        // Square - subclass
        function Square(){
            Shape.call(this);
        }

        Rectangle.prototype = Object.create(Shape.prototype);
        Square.prototype=Object.create(Rectangle.prototype);

        var rect = new Rectangle();

        var sq= new Square();

        sq.x=1;
        sq.y=1;
        sq.move(1,1);

Поскольку метод move не может быть найден в Square.prototype, поэтому JavaScript найдет его в своих родительских объектах, следующих по цепочке, я думал, что он будет найден в Rectangle.prototype, но на самом деле он находится в корне Shape.prototype, так что я не могу понять, почему sq.move(1,1) на самом деле вызывает Shape.prototype.move вместо вызова метода move Rectangle.prototype ? Я что-то пропустил? Спасибо.


person Joe.wang    schedule 15.05.2013    source источник
comment
Должен ли конструктор Square() вызывать Rectangle(), а не Shape()?   -  person nnnnnn    schedule 15.05.2013
comment
Поскольку Square является подклассом Shape, а не подклассом Rectangle (?)   -  person DaGLiMiOuX    schedule 15.05.2013
comment
@All Позвольте мне попробовать, я думаю, это не проблема.   -  person Joe.wang    schedule 15.05.2013
comment
Разве Retangle.prototype = new Shape() не проще, чем Object.create()?   -  person Ja͢ck    schedule 15.05.2013
comment
@All, метод call просто вызывает constructor, это не имеет значения для объекта prototype. Кстати, обычно цепочка наследования всегда связана с prototype объекта. constructor используется только для построения созданного объекта.   -  person Joe.wang    schedule 15.05.2013
comment
@ Джек +1 Верно, они оба в порядке. Это зависит от вашего стиля кода.   -  person Joe.wang    schedule 15.05.2013
comment
Тогда что у вас есть Superclass - Shape() => Subclass - Rectangle() => Subclass of a subclass - Square() ?   -  person DaGLiMiOuX    schedule 15.05.2013
comment
@DaGLiMiOuX да, верно.   -  person Joe.wang    schedule 15.05.2013


Ответы (2)


Вы только что перезаписали свой Rectangle.prototype, в котором уже было move. Поскольку вы перезаписали его, прикрепленного вами move больше нет, поэтому используется ход Shape.

Rectangle.prototype.move = function(x, y) {
  this.x += x;
  this.y += y;
  alert('Rectangle move');
};

function Square(){
  Shape.call(this);
}

//overwritten the prototype
Rectangle.prototype = Object.create(Shape.prototype);

Сначала создайте объект-прототип, прежде чем добавлять к нему.

Rectangle.prototype = Object.create(Shape.prototype);
Rectangle.prototype.move = function (x, y) {
  this.x += x;
  this.y += y;
  alert('Rectangle move');
};
person Joseph    schedule 15.05.2013
comment
Это не имеет ничего общего с подъемом; код просто перезаписывает Rectangle.prototype :) - person Ja͢ck; 15.05.2013
comment
@Джек О да. Его код был настолько смешанным, что я сначала так и подумал. Спасибо - person Joseph; 15.05.2013
comment
@JosephtheDreamer Теперь я знаю причину! Object.create назначит другой экземпляр Rectangle.prototype, поэтому в моем коде больше не существует метода move в Rectangle.prototype, потому что есть другой объект, переопределяющий предыдущий. Надеюсь, вы подтвердите мое понимание. Спасибо. - person Joe.wang; 15.05.2013
comment
переопределить ----› перезаписать извините за опечатку. - person Joe.wang; 15.05.2013

Переместите расширение прототипа вниз. Теперь вы назначаете прототип после его расширения, поэтому он перезапишет расширенный.

//Shape - superclass
        function Shape() {
          this.x = 0;
          this.y = 0;
        };
        // Rectangle - subclass
        function Rectangle() {
          Shape.call(this); //call super constructor.
        }
        // Square - subclass
        function Square(){
            Shape.call(this);
        }    

        Rectangle.prototype = Object.create(Shape.prototype);
        Square.prototype = Object.create(Rectangle.prototype);

        Shape.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;

            alert('Shape move');
        };
        Rectangle.prototype.move = function(x, y) {
            this.x += x;
            this.y += y;

            alert('Rectangle move');
        };

        var rect = new Rectangle();
        var sq = new Square();

        sq.x=1;
        sq.y=1;
        sq.move(1,1);
person Sarath    schedule 15.05.2013