简体   繁体   中英

JavaScript function parameter referencing object

I have been creating a game, similar to agar.io , but have noticed some strange behaviour when passing an object into a function.

I have simplified the code to highlight the problem. In the code, I pass the object gameData as a parameter into update , but when I change the parameter within the function, it passes the changes to the referenced object.

If you run the code, the gameData object, which is being printed to the console, will continue to increase, despite not directly changing it.

I am not sure what is going on here, I would like to understand why this happens and how to get around it. I have managed to fix it with the line

update({x: gameData.x, y: gameData.y})

but this isn't clean code, and doesn't explain the behaviour.

Regards, Callum Live code in jsfiddle

var gameData = {
    x: 0,
    y: 0
};

setInterval(heartbeat, 1000 /1);

function heartbeat() {
    console.log('=====================');
    update({x: gameData.x, y: gameData.y}); // doesn't update object
    update(gameData);                      // updates object
    // gameData = update(gameData);
}

function update(data) { 
    data.x += 1;
    data.y += 1;

    console.log('gameData', gameData);

    // return data;
}

update({x: gameData.x, y: gameData.y});

this line creates a new object containing x and y attributes, that you pass to your update function, but gameData is a global variable you are working with. so when calling update with the new object you just created, updates the values of that new object, and they are not saved anywhere after the function call.

but

update(gameData);

gets the gameData object as the argument and updates x and y values of the gameData object that is referenced to the global variable you defined at the top of your code, and when in console.log(gameData) you see the values in this object.

NOTE:

I don't recommend using a global variable and calling a function that does not return anything, instead you can create a function like this:

function update(data){
    return { x: data.x + 1, y: data.y + 1 }
}

and call it like this:

gameData = update(gameData)

I think this example is really interesting. I'll try to explain how it works in details.

As we see that, our codes called the update() function twice, however, somehow, the gameData object is only updated once.

Let's see:

function heartbeat() {
    update({x: gameData.x, y: gameData.y});  // I see this as a getter
    update(gameData);                        // I see this as a setter
}

For the first invocation, we actually pass the primitive values of gameData.x and gameData.y in form of an object. They are actually only primitive values , not references . Any actions we made on these primitive values will not affect the actual object which is stored somewhere in memory.

For the second invocation, we passed a reference of the gameData object, therefore, when you reassign the gameData.x and gameData.y properties to the new values, they directly affect the actual object in the memory. That's why we receive the new value of those properties when invoking console.log(gameData) .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM