簡體   English   中英

向原型添加方法

[英]Add a method to prototype

我創建了一個Sprite類,然后從Sprite類派生了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);

Sprite構造函數相反, Dragon函數確實return一個對象-因此不再是構造函數,而只是一個工廠函數。 它確實創建並返回一個Sprite實例,該實例將從Sprite.prototype繼承,而不是Dragon.prototype繼承。 請參閱JavaScript中的“ new”關鍵字是什么? 有關詳細信息。

要解決此問題,請使用Dragon作為構造函數。 this將是實例,並要初始化它,您需要.call()它調用Sprite函數,然后再賦予它特定於.call()屬性。 然后,新創建的實例將從Dragon.prototype繼承。

為了正確設置原型鏈,您需要使Dragon.prototype繼承自Sprite.prototype以便所有創建的Dragon實例也將具有Sprite方法,如此

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);

執行Dragon.prototype.action操作時未調用Dragon.prototype.action的原因:

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

是因為你選擇返回一個新創建的Sprite從對象Dragon的構造函數,而不是使用this ,這將被設置為新Dragon在已經被稱為與實例為你new 因為您顯式地使用new調用Sprint構造函數,然后返回該對象,所以該對象已使用Sprite的原型進行了設置(並且對Dragon一無所知)。

有幾種方法可以在JavaScript中進行繼承,但是我認為在您的情況下,只需更改Dragon構造函數以顯式指定此方法調用Sprite ,而讓它作用於新的Dragon對象,您就可以擺脫這種情況:

var Dragon = function( x, y, width, height){
    Sprite.call(this, dragonSheet,4,3,x,y, width,height); // act on `this`
    this.frameSpeed = .5;
    this.xSpeed = 4;
    // 'return this' is implied for constructors
} 

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM