声明具有相同名称的变量会导致socket io出现问题

时间:2017-07-12 21:53:56

标签: node.js socket.io

我花了一段时间才弄清问题是什么,但我想知道为什么它会像那样。

使用此代码,变量播放器,播放器和套接字将不确定,从而导致错误。

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之后的代码导致播放器未定义。

那么,为什么会这样呢?

2 个答案:

答案 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');
    }
});