@NicoBurno
Разработчик-прокрастинатор

Почему после вызова функции меняется объект?

Есть вот такой, упрощенный код:
var Game = function (players) {
	this.game = {
		players: []
	};

	console.log(this.getStateWithMe(players[0]).players); //тут все нормально
	console.log(this.getStateWithMe(players[1]).players); //а тут this.game уже изменен
}

Game.prototype = {
	getStateWithMe: function (player) {
		//функция должна возвращать модифицированную копию this.game
		var g = {};
		for (prop in this.game) if (this.game.hasOwnProperty(prop)) {
			g[prop] = this.game[prop];
		}

		g.players.push(player);

		return g;
	}
}

new Game(['a', 'b']);

Я пытаюсь реализовать функцию получения дочернего объекта, в зависимости от параметра. Но проблема в том, что прототипная функция getStateWithMe() изменяет сам объект.
Как я понял это из-за того, что var создает ссылку на объект, а не его копию.
Как это поправить, оставив функцию в прототипе?
  • Вопрос задан
  • 314 просмотров
Решения вопроса 1
k12th
@k12th
console.log(`You're pulling my leg, right?`);
Нет, это потому что this.game.players является массивом, и, соответственно, ссылочным типом. То есть g.players и this.game.players ссылается на один и тот же объект.

Вам нужна функция, которая делает deep clone. Самый лаконичный способ, который я знаю — JSON.parse(JSON.stringify(this.game)), если у вас там нет хитрых данных типа дат и регекспов, то все должно быть нормально.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 2
xytop
@xytop
PHP/RoR web dev & tech lead
var g = jQuery.extend(new Game([]), this.game);
Ответ написан
keslo
@keslo
var Game = function (players) {
  this.game = {
    players: []
  };

  console.log(this.getStateWithMe(players[0]).players); // тут все нормально
  console.log(this.getStateWithMe(players[1]).players); // и тут вроде тоже
}

Game.prototype = {
  getStateWithMe: function (player) {

    var g = {};
    g.players = this.game.players.slice(0); // копируем массив-значение из this.game.players
    g.players.push(player);

    return g;
  }
}

new Game(['a', 'b']);
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
30 апр. 2024, в 23:39
3000 руб./за проект
30 апр. 2024, в 23:32
1500 руб./за проект
30 апр. 2024, в 22:44
500 руб./в час