我花了一段时间才弄清问题是什么,但我想知道为什么它会像那样。
使用此代码,变量播放器,播放器和套接字将不确定,从而导致错误。
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID = data;
player.gameID=gameID;
var game = GAME_LIST[gameID];
game.players[socket.id]=player;
var players = game.players;
for (var p in players){
var player = players[p];
var socket = player.socket;
socket.emit('playerJoined');
}
});
避免使用相同名称的变量声明,这一切都能正常工作。
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID = data;
player.gameID=gameID;
var game = GAME_LIST[gameID];
game.players[socket.id]=player;
var tempPlayers = game.players;
for (var p in tempPlayers){
var tempPlayer = tempPlayers[p];
var tempSocket = tempPlayer.socket;
tempSocket.emit('playerJoined');
}
});
有趣的是,当我运行第一个代码时,它表示行player.gameID=gameID
中的播放器未定义,而如果我删除了player.gameID=gameID
之后的代码,则播放器已定义。基本上,player.gameID=gameID
之后的代码导致播放器未定义。
那么,为什么会这样呢?
答案 0 :(得分:2)
声明var player = players[p];
时,它是为整个函数范围声明的(for循环没有自己的范围)。
在执行函数体之前,在开始时全部评估当前范围中的名称。
因此,当调用function(data)
时,即使在执行player
之前,也会在该范围内覆盖名称var gameID = data;
。
一个最小的例子:
> var x = 'foo';
> f = function() { console.log(x); var x = 'bar'; }
> f()
undefined
答案 1 :(得分:1)
Javascript将变量的声明移动到它们定义的作用域的顶部,并为它们提供未定义的初始值,但保留了赋值。这称为提升
您的代码相当于:
var player = Player(socket.id, socket);
socket.on('joinHost', function(data) {
var gameID; // undefined
var game; // undefined
var players; // undefined
var player; // undefined
var socket; // undefined
gameID = data;
player.gameID=gameID; // can't set property 'gameID' of undefined
game = GAME_LIST[gameID];
game.players[socket.id]=player; // is undefined since 'player' is undefined at this stage
players = game.players; // undefined
for (var p in players){
player = players[p];
socket = player.socket;
socket.emit('playerJoined');
}
});