Я создавал игру, похожую на agar.io, но заметил странное поведение при передаче объекта в функцию.
Я упростил код, чтобы выделить проблему. В коде я передаю объект gameData в качестве параметра в update, но когда я изменяю параметр внутри функции, он передает изменения в объект, на который имеется ссылка.
Если вы запустите код, объект gameData, который выводится на консоль, продолжит увеличиваться, несмотря на то, что напрямую не изменил его.
Я не уверен, что здесь происходит, я хотел бы понять, почему это происходит и как это обойти. Мне удалось исправить это с помощью линии
update({x: gameData.x, y: gameData.y})
но это не чистый код и не объясняет поведение.
С уважением, Каллум Живой код в jsfiddle
var gameData = {
x: 0,
y: 0
};
setInterval(heartbeat, 1000 /1);
function heartbeat() {
console.info('=====================');
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.info('gameData', gameData);
// return data;
}



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


update({x: gameData.x, y: gameData.y});
эта строка создает новый объект, содержащий атрибуты x и y, который вы передаете своей функции update, но gameData - это глобальная переменная, с которой вы работаете. поэтому при вызове update с новым объектом, который вы только что создали, обновляет значения этого нового объекта, и они нигде не сохраняются после вызова функции.
но
update(gameData);
получает объект gameData в качестве аргумента и обновляет значения x и y объекта gameData, который ссылается на глобальную переменную, которую вы определили в верхней части кода, а в console.info(gameData) вы видите значения в этом объекте.
ЗАМЕТКА:
Я не рекомендую использовать глобальную переменную и вызывать функцию, которая ничего не возвращает, вместо этого вы можете создать такую функцию:
function update(data){
return { x: data.x + 1, y: data.y + 1 }
}
и назовите это так:
gameData = update(gameData)
Ах, спасибо, в этом есть смысл. Функция изначально вернула объект, как вы можете видеть, где он был закомментирован. Однако я заметил, что он все еще работал нормально, когда я удалил оператор return. Я просто не мог понять, почему он так себя ведет. Ваше здоровье...
@Callum, вы можете отметить ответ как правильный, если он дал вам ответ! а также обратите внимание, что использование глобальных переменных всегда опасно и может привести к серьезным проблемам, если вы пытаетесь добиться чего-то большого.
Я считаю этот пример действительно интересным. Постараюсь подробнее объяснить, как это работает.
Как мы видим, наши коды дважды вызывали функцию update(), однако каким-то образом объект gameData обновляется только один раз.
Давайте посмотрим:
function heartbeat() {
update({x: gameData.x, y: gameData.y}); // I see this as a getter
update(gameData); // I see this as a setter
}
Для первого вызова мы фактически передаем примитивные значенияgameData.x и gameData.y в форме объекта. На самом деле это только примитивные значения, а не использованная литература. Любые действия, которые мы сделали с этим примитивные значения, не повлияют на фактический объект, который хранится где-то в памяти.
Для второго вызова мы передали ссылка объекта gameData, поэтому, когда вы переназначаете свойства gameData.x и gameData.y на новые значения, они напрямую влияют на фактический объект в памяти. Вот почему мы получаем новое значение этих свойств при вызове console.info(gameData).
Так работает JavaScript (и многие другие языки). Объект как значение на самом деле является ссылка для объекта. Представьте себе последствия для производительности, если бы объекты копировались при передаче в функции.