添加一个原型方法

时间:2014-10-20 20:05:38

标签: javascript prototype prototype-chain

我创建了一个Sprite类,然后从sprite类派生了一个Dragon类。我试图只在Dragon类中添加一个动作方法,但它不起作用。我将动作方法添加到Dragon.prototype的方式与使用Sprite.prototype将方法添加到Sprite类的方法相同,但是如果我创建了Dragon类的实例,我就无法调用我在Dragon原型中定义的动作方法。

如果我将Dragon.prototype.action更改为Sprite.prototype.action,则代码完美无缺。对于这个例子,它并不重要,但我希望以后能够为特定的类设置方法。我究竟做错了什么?我应该解决更多方法名称吗?如果答案显而易见,我道歉,感谢您的帮助。

var Sprite = function(spriteSheet, rows, columns, x, y, width, height){
    this.frameSpeed = 1;
    this.spriteSheet = spriteSheet;
//The starting Location
    this.x = x;
    this.y = y;
//The width and height of the sprite
    this.width = width;
    this.height = height;
//Variables for movement
    this.xSpeed = 0;
    this.ySpeed = 0;
//rows and columns of our spritesheet
    this.rows = rows;
    this.columns = columns;
//our variables needed to animate the sprite.
    this.sourceWidth = this.spriteSheet.width/this.columns;
    this.sourceHeight = this.spriteSheet.height/this.rows;
    this.sourceX = 0;
    this.sourceY = 0;
    this.frameCount = this.rows * this.columns;
    this.currentFrame = 0;
}

Sprite.prototype.update = function(){

    this.y+=this.ySpeed;
    this.x+= this.xSpeed;

    if(this.currentFrame >= this.frameCount){
        this.currentFrame = 0;
    }

    this.row = Math.floor( this.currentFrame / this.columns);
    this.column = Math.floor( this.currentFrame % this.columns);

    this.currentFrame+=this.frameSpeed;
    this.sourceX = this.column * this.sourceWidth;
    this.sourceY = this.row * this.sourceHeight;

}

Sprite.prototype.draw = function(){
     context.drawImage( this.spriteSheet, this.sourceX, this.sourceY, this.sourceWidth, this.sourceHeight, this.x, this.y, this.width, this.height);
}

var mySprite = new Sprite(smiley,4,4,100,50,100,100);

var Dragon = function( x, y, width, height){
    var dragon = new Sprite(dragonSheet,4,3,x,y, width,height);
    dragon.frameSpeed = .5;
    dragon.xSpeed = 4;
    return dragon;
} 

Dragon.prototype.action = function(){
    if(this.x>500){
        this.x = -100;
    }
}

var dragon1 = new Dragon(70,170,80,50);

2 个答案:

答案 0 :(得分:2)

Sprite构造函数相比,Dragon函数确实return一个对象 - 因此不再是构造函数,而只是一个工厂函数。它确实创建并返回Sprite实例,该实例将从Sprite.prototype继承,而不是从Dragon.prototype继承。有关详细信息,请参阅What is the 'new' keyword in JavaScript?

要解决此问题,请使用Dragon作为构造函数。 this将成为实例,并且在为其提供特定于龙的属性之前,先对其进行初始化.call() Sprite函数。然后,新创建的实例将从Dragon.prototype继承。

要正确设置原型链,您需要从Dragon.prototype继承Sprite.prototype - 以便所有已创建的Dragon实例也具有Sprite方法,比如here

function Dragon(x, y, width, height) {
    Sprite.call(this, dragonSheet, 4, 3, x, y, width, height);
    this.frameSpeed = .5;
    this.xSpeed = 4;
}
Dragon.prototype = Object.create(Sprite.prototype);
Dragon.prototype.constructor = Dragon;

Dragon.prototype.action = …;

var dragon1 = new Dragon(70,170,80,50);

答案 1 :(得分:0)

当您执行以下操作时未调用Dragon.prototype.action的原因:

var d = new Dragon(...);
d.action(); // won't work

是因为您选择从Sprite构造函数返回新创建的Dragon对象,而不是使用this,它将被设置为新{{1}用Dragon调用后的实例。因为您使用new显式调用new构造函数,然后返回该对象,所以该对象已使用Sprite的原型进行设置(并且对Dragon没有任何了解)。

有几种方法可以在JavaScript中进行继承,但我认为在您的情况下,只需更改Sprint构造函数即可明确指定Dragon,而不是让它作用于你的新Dragon对象:

Sprite