2014-04-24 79 views
0

我想創建一個JavaScript「類」,它工作的很好,但Engine.tile.draw不能按預期工作。我似乎無法讓它在Engine.start內工作。是不是可以創建一個對象並在其中添加一個函數,就像我一樣?你們會怎麼做?任何幫助表示讚賞。 :)創建一個包含函數的對象的JavaScript類

var EngineClass = (function() { 
    var Engine = function() { 
     this.canvas = document.getElementById('game'); 
     this.handle = this.canvas.getContext('2d'); 
    }; 

    Engine.prototype.start = function (mapData) { 
     this.tile.draw(mapData); 
    }; 

    Engine.prototype.tile = { 
     draw: function (x, y, tile) { 
     this.handle.fillText(tile, x * 16, y * 16); 
     }; 
    } 

    return Engine; 
})(); 

var Engine = new EngineClass(); 
+1

JavaScript是一種基於原型的面嚮對象語言(http://en.wikipedia.org/ wiki/Prototype-based_programming),而不是基於類的面向對象的語言。只是不要這樣做。你不會在你的車裏建一個割草機,所以不要在JS裏建立類。 – schlingel

+1

javascript中沒有類 – defau1t

+0

這就是我說「class」的原因。我知道當前版本中沒有任何類別的ECMA,但這是模擬它的常用方法。但是我嘗試在一個對象(Engine.tile)中添加函數的部分並不常見,因爲它不起作用。 – Jan

回答

0

它並沒有真正的工作使用子-bjects喜歡你現在的位置:

Engine.prototype.tile = { 
    draw: function (x, y, tile) { 
    this.handle.fillText(tile, x * 16, y * 16); 
    }; 
} 

的問題是,當你調用Engine.tile.draw(),則this指針draw()方法裏面會設置爲tile對象,這不是您的代碼所假設的(您的代碼假定this指向Engine實例,這不會發生)。

如果你真的想要這樣的子對象,那麼你需要在Engine構造函數中初始化那個子對象,這樣每個對象都被獨立設置,然後你需要將它的引擎指針添加到tile實例數據,以便在調用Engine.tile.draw()時,可以從指向tile對象的this指針獲取適當的Engine實例。但是,這一切都很糟糕,可能既是不必要的,也是艱難的做事方式。

你或許應該用自己的實例數據製作自己的對象tile,或者在Engine對象上放置draw方法,並傳遞一些參數來幫助它完成工作。

+0

我很感謝你的回答,謝謝。所以基本上,你的建議是把「瓷磚」作爲自己的對象?瓷磚將會包含更多後,所以我想這是一個好主意。 – Jan

+0

@Jan - 如果'tile'將有很多自己的操作和數據,那麼是的,你應該把它作爲自己的對象。如果爲了「繪製()」本身,它需要知道它應該用於繪製的「句柄」,那麼也許應該將它存儲在'tile'實例數據中,以便它可以執行'draw() '方法本身。或者,你可以讓每個'tile'有一個對其父'Engine'的引用,並且你可以從那裏獲得'handle'。重點在於,當在'tile'對象上調用方法時,'this'指針將成爲'tile'對象。 – jfriend00

0

上面的評論說你不應該試圖強制JavaScript是一種原型語言的類是正確的。

從技術上說,不起作用的原因是,無論何時使用點符號調用函數(例如something.method()),該函數都會被綁定到點左側的this調用。因此,在這種情況下,當您說this.tile.draw(mapData)時,將調用tile.draw函數,thistile對象,而不是您期望的Engine對象。

有幾種方法可以解決這個問題,但最好的建議是將您的思維轉換到JavaScript的原型系統,而不是試圖強迫您的基於類的思維。

0

因爲this裏面draw函數會參考Engine.prototype.tile對象,而不是你所期望的。

變化

Engine.prototype.tile = { 
    draw: function (x, y, tile) { 
    this.handle.fillText(tile, x * 16, y * 16); 
    }; 
} 

Engine.prototype.tile = function() { 
    var self = this; 
    return { 
    draw: function (x, y, tile) { 
     self.handle.fillText(tile, x * 16, y * 16); 
    }; 
    }; 
} 

,並調用它像:

Engine.prototype.start = function (mapData) { 
    this.tile().draw(mapData); 
}; 
相關問題