Object updating unexpectedly

Object updating unexpectedly
0

#1

Hello! I have had the same problem with my Tic Tac Toe game and now the Simon Game. Basically, I have a default game object that I’m trying to use for the reset functions in both games. It looks something like this:

const defaultGame = {
  strict: strict,
  currentPattern: [],
  selectedPattern: [],
  maxLength: maxLength,
  patternLength: 1,
  attempts: 0,
  speed: 1
}

To start a game, I instantiate a new Game object and set up a new game from the default:

const Game = function() {
  this.game = {...defaultGame};
};

Throughout the game, object properties get updated by various functions. When the game is over or the user hits ‘reset’, the reset function just does this:

Game.prototype.reset = function() {
  this.game = {...defaultGame};
};

I would expect this to replace this.game from the constructor with the defaultGame object. However, when I console.log(defaultGame) in the reset function, it’s taken on the properties updated throughout the game, instead of remaining unchanged as I would have expected.

Why is defaultGame even changing?

Source


#2

this is not a deep copy

this.game = {...defaultGame}

arrays or objects in defaultGame are not copied - this.game.currentPattern is the same array as defaultGame.currentPattern

btw if you are learning javascript it’s much better to start with es6 classes for cleaner class design and code


#3

I sort of disagree with this. Es6 classes are convenient syntactic sugar, but they makeep the classes look like Java classes (sort of the point) when they don’t work like Java classes. I’d say it’s better to learn how prototypes and prototypal inheritance work first, otherwise the code you read (written by others) won’t make sense.


#4

es6 including classes is the best thing to happen to javascript in a long time - when you read and write es6 class-based code it reads nice and looks nice with meaningful keywords that reflect a class-oriented design - I understand people can remain stuck in legacy code and thinking for a long time - it does not have to be so for newcomers to javascript


#5

Thanks! I was interpreting ‘clone’ as ‘the same thing’ when reading documentation. Will keep digging.

I’ve already started with prototypes, but am curious to experiment and try other ways. I’ve been using React for most of these front-end projects, but would likely learn far more building something with ES6 classes from scratch. Perhaps for the next project, or a later refactor of this one.


#7

Actually the object spread operator (...defaultGame) is supposed to do what you want, but it isn’t supported in most browsers yet without transpiling.

Try this.game = Object.assign({}, defaultGame);. This should create a new empty object and assign the properties from defaultGame to it.


#8

I tried this and had the same problem.

For now I have changed this so a new game is returned by a function:

Game.prototype.newGame = function() {
  return {
    strict: strict,
    currentPattern: [],
    selectedPattern: [],
    maxLength: maxLength,
    patternLength: 1,
    attempts: 0,
    speed: 1
  }
};

Then, this.game = this.newGame() returns what I want. Now I’m curious to know what the difference is between a shallow and deep copy, and what use-cases there are for a shallow copy. Gets to Googling


#9

I don’t disagree with this. Many ES6 features are HUGE improvements over the ES5 way of doing things. However, I do think that it is important to understand what the language actually does. I have no issue with using ES6 classes, I just think you should learn how prototypal inheritance works FIRST, because it is not the same as most languages with a class keyword. I suppose this is less of an issue if JS is your first programming language, which is probably the case for many people here, but then the same problem will apply when they learn a second language just in the opposite order.

If anything, shoehorning OOP into everything regardless of whether the language actually does OOP is “legacy thinking”. Besides, anyone working professionally is going to have to work with, and understand, legacy code. Assuming that ES6 classes work the same as classes in other languages will get you into trouble eventually.

I suggest reading these for a better articulation of why I think it’s important to understand prototypes BEFORE using the syntactic sugar: Is “Class” In ES6 The New “Bad” Part?, and The Two Pillars of JavaScript.


#10

I have not referred to any language besides javascript - only you keep referring to java and “other languages”

I’m saying it’s nice to design a solution using class hierarchies and methods and have the code reflect your design with obvious keywords like “class” and “constructor” and “extends” and have setters and getters nicely called out - this has nothing to do with how a class is actually implemented - it’s more about easily mapping code to an abstract design

at some point it is important to understand how a class is implemented in javascript - it does not have to be a prerequisite to solving problems in a modular encapsulated manner


#11

Not true. Neither the object spread operator nor Object.assign make a deep copy. There are good reasons why: it is actually fiendishly difficult (or impossible, even) to define a default (implicit, built-in) deep copy that would make sense for all kinds of object; it would often be a hazard to (reasonable) efficiency. Also, of course, one often requires shallow copy rather than deep.

On the other hand, the shallow copy characteristic of JavaScript (and a lot of other languages) is a serious pain. Typically, you have to define your own deep copy functions that do the right thing for every different structure in your application that needs to be deep copied somewhere.


#12

I guess I shouldn’t answer questions when I’m reading the forums from my phone. I completely missed the “deep” part of the copy need.