Правильное наследование Javascript - PullRequest
6 голосов
/ 13 февраля 2011

Мне интересно, возможно ли наследовать конструктор в JavaScript. В следующем примере я бы хотел, чтобы Moveable присвоил x и y аргументы this.x и this.y соответственно, как я определил в Sprite Кроме того, что было бы лучшим способом (но все еще кратким и читабельным) определить прототип, не создавая природу предка? Было бы лучше назначить его в самом классе, а не во внешней области, как сейчас:

function Sprite(x, y) {
    this.x = x ? x : 0;
    this.y = y ? y : 0;     
    this.getPos = function() {
        return {
            x: this.x,
            y: this.y
        };
    };
}

function Moveable(x, y) {

}
Moveable.prototype = new Sprite();

Ответы [ 3 ]

6 голосов
/ 13 февраля 2011

Вы бы назвали родительский конструктор так:

function Moveable(x, y) {
    Sprite.call(this, x, y);
}

Боюсь, нет короткого способа настройки наследования, если вы хотите использовать псевдоклассическое наследование, и нет способа сделать это внутри области действия функции конструктора.

Вы можете обойти создание своего базового класса, если создадите временный пустой объект. Выглядит сложно, но обычно используется в качестве вспомогательной функции (как в методе Google Closure Library goog.inherits , откуда я более или менее скопировал это):

var inherits = function(childConstructor, parentConstructor) {
  function tempConstructor() {};
  tempConstructor.prototype = parentConstructor.prototype;
  childConstructor.prototype = new tempConstructor();
  childConstructor.prototype.constructor = childConstructor;
};

inherits(Moveable, Sprite);

// instantiating Moveable will call the parent constructor
var m = new Moveable(1,1);
6 голосов
/ 13 февраля 2011

Стандартный способ вызова конструктора суперкласса - это Function.call:

function Moveable(x, y) {
  Sprite.call(this, x, y);
}

Что касается прототипа, вы можете сделать что-то подобное, чтобы связать прототип без созданияэкземпляр суперкласса:

function makePrototype(superclass) {
  function f() { }
  f.prototype = superclass.prototype;
  return new f();
}

Moveable.prototype = makePrototype(Sprite);

При этом используется фиктивный конструктор для создания объекта, который использует тот же прототип, что и Sprite, и, поскольку это все, что заботит JavaScript, экземпляры Moveable считаются instanceof Sprite.

Это не "короткий и читабельный", как вы просили, но единственный другой вариант - полностью пропустить прототипы и назначить элементы непосредственно в конструкторе.

Редактировать: Как указывает @Raynos, вы также хотите установить свойство constructor (которое выполняется по умолчанию в JavaScript, но теряется при сбросе Moveable.prototype):

Moveable.prototype.constructor = Moveable;
1 голос
/ 14 февраля 2011

Думайте о функции как о двух частях: функции конструктора и объекте-прототипе. Возьмите два из этих классов функций и смешайте их вместе. Смешивать объекты достаточно просто, хитрость заключается в том, чтобы смешивать конструкторы.

var Sprite = function(x, y, w, h){
   console.log("Sprite constr:", x, y, w, h);
}

var Moveable = function(x, y, w, h){
   console.log("Moveable constr:", x, y, w, h);
}

var extend = function(class1, class2){
   // here we make a new function that calls the two constructors. 
   // This is the "function mix" 
   var f = function(){
      class1.prototype.constructor.apply(this, arguments);
      class2.prototype.constructor.apply(this, arguments);
   }
   // now mix the prototypes
   f.prototype = library.objectmix(class1.prototype, class2.prototype);
   return f;
}

var MoveableSprite = extend(Sprite, Moveable);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...