使用相同的名称声明variables导致socket io中的问题
我花了一段时间才弄清楚是什么问题,但我想知道为什么这样做。
使用这个代码,variables播放器,播放器和套接字将是未定义的,导致错误。
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'); } });
避免使用相同名称的variables的声明使所有工作正常。
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
之后的代码导致玩家未定义。
那么,为什么会这样呢?
当你声明var player = players[p];
它被声明为整个函数范围(for循环没有它自己的范围)。
在执行函数体之前,当前范围中的名称将在开始时被全部评估。
所以当function(data)
时,即使在var gameID = data;
之前,名称player
也会在该范围内重写var gameID = data;
被执行。
一个最小的例子:
> var x = 'foo'; > f = function() { console.log(x); var x = 'bar'; } > f() undefined
JavaScript将variables的声明移动到它们定义的范围的顶部,并给它们一个未定义的初始值,但保持赋值。 这叫做吊装
您的代码相当于:
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'); } });