user1124 user1124 - 3 months ago 10
Node.js Question

node for loop unintentionally changing the object

I have an angular app that talks to a node.js socket server that talks to node.js app server. In this socket server function, I'd like to scrub the app server's response depending on which user. I make a copy emitHand of the to-be-scrubbed object hand and send the copy to the client. It looks like the copy is effecting the original object because the loop stops after the first and other clients don't get the message.

The first console output shows that the second client is connected and in the clientsSockets list before the data manipulation. So I should only see "user not connected" 4 times.

The second console output shows the original object hand.players is changing when it is never called. This is my question. Why does hand.players change when only emitHand.players is changing in the code? I also tried a forEach(commented out) to no avail.

socket.on('hand', function(receivedHand) {
console.log('clientSockets[56fde5327ee729ac1a37fd1c].userId '+ util.inspect( clientSockets['56fde5327ee729ac1a37fd1c'].userId, false, null));
var hand = null;
PostHand(receivedHand).then(function(data) {
hand = JSON.parse(data);
console.log('hand.players'+util.inspect(hand.players, false,null));
var emitHand=hand;
// emitHand.players.forEach(function(player, index, handPlayers) {
for(var index in emitHand.players){var player=emitHand.players[index];
if (clientSockets[player.userId]!=null){
ScrubHand(emitHand.players,index).then(function(data) {
emitHand.players=data.emitHandPlayers;
clientSockets[data.emitHandPlayers[data.index].userId].socket.emit('hand', emitHand);
console.log('hand.players'+util.inspect(hand.players, false,null));
});
}else{
console.log('user not connected'+player.userId);
}
}
// });
});
});


This is the output.

clientSockets[56fde5327ee729ac1a37fd1c].userId '56fde5327ee729ac1a37fd1c'
hand.players[ { userId: '56ccbc3992d91b401b62f850',
seat: 1 },
{ userId: '56ccbc9c92d91b401b62f857',
seat: 2 },
{ userId: '56fde4ec2ecc97901f232f65',
seat: 3 },
{ userId: '56fde5327ee729ac1a37fd1c',
seat: 4 },
{ userId: '56fdef1347636f50171c5026',
seat: 5 },
{ userId: '5720f4d718e3775020bdaf17',
seat: 6 } ]
user not connectednull
user not connectednull
user not connectednull
user not connectednull
user not connectednull
hand.players[ { userId: '56ccbc3992d91b401b62f850',
seat: 1},
{ userId: null,
seat: 2},
{ userId: null,
seat: 3},
{ userId: null,
seat: 4},
{ userId: null,
seat: 5},
{ userId: null,
seat: 6} ]

Answer

It's because hands and emitHand are the same object. In Javascript, all objects are called by reference. So when you var emitHand=hand;, you just get another reference to the same Object.

You would need to clone the object, if you want a hard copy:

var emitHand = JSON.parse(JSON.stringify(hand));

You might want to take a look at:

What is the most efficient way to clone an object in JavaScript?