Batash
Batash

Reputation: 111

declaring variable with same name causes problems in socket io

It took me a while to figure out what the problem was, but I'm wondering why it's acting like that.

Using this code, the variables player, players and socket will be undefined, causing errors.

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

Avoiding the declarations of variables with same names makes it all work correctly.

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

The interesting part is, when I ran the first code, it says the player in the line player.gameID=gameID is undefined, while if I removed the code which is after player.gameID=gameID, the player was defined. Basically, the code after player.gameID=gameID caused the player to be undefined.

So, why is this happening?

Upvotes: 1

Views: 77

Answers (2)

taha
taha

Reputation: 1017

Javascript moves variables's declaration to the top of the scope they were defined and gives them an undefined initial value but keeps assignment in place. This is called hoisting

Your code is equivalent to :

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

Upvotes: 1

Joao Delgado
Joao Delgado

Reputation: 856

When you declare var player = players[p]; it is declared for the whole function scope (the for loop doesn't has a scope of it's own).

The names in the current scope are evaluated all in the beginning, before executing the function body.

So when function(data) is called, the name player is overridden in that scope even before var gameID = data; is executed.

A minimal example:

> var x = 'foo';
> f = function() { console.log(x); var x = 'bar'; }
> f()
undefined

Upvotes: 2

Related Questions