2017-03-01 40 views
0

我有一個nodeJS應用程序需要player.js。在player.js中,我定義了Player並添加了方法Player.updatePacket,但是當我需要它在main.js中並創建播放器實例時,player.updatePacket未定義。功能未定義後module.export從另一個文件

player.js:

module.exports.PLAYER_LIST = {}; 
var Player = exports.Player = {} 

//constructor 
Player.create = function(id) { 
    var tmp = { 
     id: id, 
     x: 0, 
     y: 0 
    }; 
    PLAYER_LIST[id] = tmp; 
    return tmp; 
} 

Player.updatePacket = function() { 
    return { 
     id: this.id, 
     x: this.x, 
     y: this.y 
    } 
} 

main.js:

var Player = require('./player.js') 

//get called by socket.io when a client connects 
//didn't include socket.io setup in example for brevity, but this function 
//is called as expected.  
io.sockets.on('connection', function(socket){ 
    var player = new Player(socket.id) 

}); 

setInterval(function() { 
    var dataArr = []; 
    for(var i in Player.PLAYER_LIST) { 
     var player = Player.PLAYER_LIST[i]; 
     console.log(player); //this logs: [Function] 
     dataArr += player.updatePacket(); //throws TypeError: not a function 
    } 
    broadcast("update", dataArr); 
}, 1000/25); 

我試圖移動出口語句的player.js底部,並把updatePacket: function() {/*function contents*/}在TMP對象,我仍然得到同樣的錯誤。任何幫助或解釋讚賞。

+1

也有一個錯誤,你不能+ =上的對象。也就是說,你的dataArr是一個對象而不是一個數組。另外,PLAYER_LIST在哪裏? – derp

+0

更新OP顯示PLAYER_LIST並將dataArr更改爲實際數組 –

回答

2

你的模塊的出口是有一個.Player屬性的對象:

var Player = exports.Player = {}; 
//   ^^^^^^^^^^^^^^^^ 

這樣,你需要的時候,你希望你的Player對象訪問屬性:

/* main.js */ 
var Player = require('./player.js').Player; 
//         ^^^^^^^ 

的(優選)替代方案是使Player的出口對象本身(「別名」):

/* player.js */ 
var Player = exports; // or = module.exports; 

如果您想要使用除默認對象之外的其他內容,則不能使用exports,但必須使用assign to module.exports

+0

我進行了首選更改,但仍然收到相同的錯誤。奇怪的是,錯誤隨機地變爲'TypeError:Player不是'var player = new Player(id)''上的構造函數'。只需運行相同的代碼大約五次就會隨機產生這兩個錯誤 –

+1

這可能是一種競爭條件,因爲您的函數異步執行,無論哪個先發生,都會得到異常。但是,是的,兩者都顯得不對。 'Player'不是一個構造函數 - 要麼讓它成爲一個類,要麼想調用'Player.create'而不是'new Player','updatePacket'被寫成'Player'上的靜態方法,而不是方法玩家對象。你可以使用'Player.updatePacket.call(player)',但我真的認爲你正在尋找'class'構造。 – Bergi

+0

感謝,澄清了很多。我正在使用ES6類的語法,因爲我發現大多數例子都是這樣寫的。我怎樣才能讓updatePacket成爲Player上的一個實例方法呢,還是隻能通過類來實現呢? –

3

試試這個

Player.js

var PlayerList = module.exports.PLAYER_LIST = {}; 
var Player = module.exports.Player = function(id) { 
    this.id = id; 
    this.x = 0; 
    this.y = 0 
    PlayerList[id] = this; 
}; 

Player.prototype.updatePacket = function() { 
    return { 
     id: this.id, 
     x: this.x, 
     y: this.y 
    } 
}; 

Main.js

var Player = require('./player.js').Player; 
var PLAYER_LIST = require('./player.js').PLAYER_LIST; 

io.sockets.on('connection', function(socket){ 
    var player = new Player(socket.id) 

}); 

setInterval(function() { 
    var dataArr = []; 
    for(var i in PLAYER_LIST) { 
     var player = PLAYER_LIST[i]; 
     console.log(player); 
     dataArr.push(player.updatePacket()); //note that it is push not += when adding items to an array 
    } 
    broadcast("update", dataArr); 
}, 1000/25); 

這種解釋可能是一個過於簡單化,但在JS, '類' 是功能,爲了增加方法放到類上,我們必須將它們添加到原型中。當我們在該類上使用'new'時,它會繼承其原型鏈上存在的所有方法。

此鏈接可能被證明是一個更好的解釋 https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Object/prototype

+0

Player.prototype是未定義的,所以Player.prototype.updatePacket會產生一個錯誤。我將嘗試使用ES6類語法重新實現此操作,但這種解釋仍然有幫助。 –

+0

感謝您的編輯,事實證明,從構造函數返回另一個對象會對原型鏈接造成嚴重破壞。 https://jsfiddle.net/g6pL9kkt/ – derp