Дочерний класс не может вызвать метод-прототип своего родителя - PullRequest
3 голосов
/ 28 декабря 2011

Я изучаю прототипы JS.

С языковой точки Java Я ожидаю, что объект SpecificRectangle будет иметь доступ к методу area(), поскольку area () - это метод его родительского прототипа (класса Rectangle).

function Rectangle(w,h){
 this.width = w;
 this.height=h;
}
Rectangle.prototype.area = function(){return this.width*this.height}

function SpecificRectangle(w,h,angle){
  Rectangle.call(this,w,h);
  SpecificRectangle.prototype=new Rectangle();
}

var specrec = new SpecificRectangle(7,8,45);

В общем, я не могу вызвать area() метод для SpecificRectangle экземпляра.
Получена стандартная ошибка JS:

TypeError: specrec.area is not a function
[Break On This Error] specrec.area() 

Каково объяснение и причина такой инкапсуляции?

Ответы [ 2 ]

3 голосов
/ 28 декабря 2011

Честно говоря, я не знаю точной причины, но вам нужно установить прототип вне функции конструктора:

function SpecificRectangle(w, h, angle) {
    Rectangle.call(this,w,h);
}

SpecificRectangle.prototype = new Rectangle();
SpecificRectangle.prototype.constructor = SpecificRectangle; // Otherwise instances of SpecificRectangle would have a constructor of Rectangle

Рабочий пример здесь .


Редактировать после комментария @herby:

Похоже, что верхний метод может нарушить наследование прототипа в зависимости от того, как построен конструктор суперкласса (см. thisarticle ).

Более надежное решение - использовать Object.create ( source - спасибо herby)

// in case Object.create does not exist
if (typeof Object.create !== 'function') {
    Object.create = function(o) {
        var F = function() {};
        F.prototype = o;
        return new F();
    };
}

function Rectangle(w, h) {
    this.width = w;
    this.height = h;
}
Rectangle.prototype.area = function() {
    return this.width * this.height
}

function SpecificRectangle(w, h, angle) {
    Rectangle.call(this, w, h);
}

SpecificRectangle.prototype = Object.create(Rectangle.prototype);
SpecificRectangle.prototype.constructor = SpecificRectangle;

var r = new SpecificRectangle(100, 50, 30);
alert(r.area());

Обновлен пример jsfiddle

1 голос
/ 28 декабря 2011

Вы должны скопировать прототип базового класса. Например:

function Rectangle(w,h){
    this.width = w;
    this.height=h;
}
Rectangle.prototype.area = function(){return this.width*this.height}

function SpecificRectangle(w,h,angle){
    Rectangle.call(this,w,h);
}
function SpecificRectangleProto(){}
SpecificRectangleProto.prototype = Rectangle.prototype;
SpecificRectangle.prototype = new SpecificRectangleProto();

var specrec = new SpecificRectangle(7,8,45);
alert(specrec.area);

Предлагаю извлечь метод расширения из некоторого фреймворка. Например ExtJS. С таким методом вы можете расширить класс следующим образом:

SpecificRectangle = extend(Rectangle, {
    constructor: function(w,h,angle){
        SpecificRectangle.superclass.constructor.call(this,w,h);
    }
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...