ababuji
ababuji

Reputation: 1731

Setting value of key in nested object happening incorrectly using a for loop and if statement

Here is an example that you can type in your console. Super new to Javascript. The example is reproducible by opening a new tab and typing it out in a console (The JSX Fiddle's console feature is in beta, so I'm not sure if it can be trusted)

let clothing = ['card0', 'card1', 'card2', 'card3'];
let timers = {}
let timerObj = {"startTime": null, "pauseTime": null, "elapsedTime": null, "hasSubmitted": false} //Nested object I want for all indices, will manipulate 0th index alone inside for loop

for (var i = 0; i < clothing.length; i++) {
  timers[i] = timerObj
  if (i == 0) {
    timers[i]["startTime"] = Date.now();
  } 
} 
console.log(timers) 

What I'm intending to do is, for the 0th index alone, set the timers[0]["startTime"] as Date.now(), and for the rest, let the startTime be null as defined in the timerObj.

Strangely, after running the for loop, I see that for all i, the Date.now() has been set. I understand that Javascript objects are mutable, but why is why are all indices being set to Date.now()?

I looked at other Javascript related Object questions related to a concept call "freezing", not sure I have my basics right.

EDIT: I think this is related the object reference being altered..

Upvotes: 0

Views: 47

Answers (3)

DNT
DNT

Reputation: 2395

Javascript does not copy objects. It passes references around, so when you assign timers[i] = timerObj once, then you assign Date.now() once , this value goes to your single timeorObj. All subsequent assignments of timerObj to timers[i] for all i refer to the single timerObj you defined.

To fix this force a copy: timers[i] = JSON.parse(JSON.stringify(timerObj));

This will serialize your clean timerObj to a JSON string, then convert it back to a new javascript object and then assign the new object to timers[i].

This way, you end up with copies of timerObj in each slot of your timers array.

Upvotes: 1

Rajneesh
Rajneesh

Reputation: 5308

You have to clone your object. There are multiple ways to clone. One would be spread operator(...). Like below:

let clothing = ['card0', 'card1', 'card2', 'card3'];
let timers = {}
let timerObj = {"startTime": null, "pauseTime": null, "elapsedTime": null, "hasSubmitted": false}

clothing.forEach((val, i)=>{
    timers[i] = {...timerObj};
    if(i==0){
       timers[i].startTime = Date.now()
    }
});
console.log(timers);

Upvotes: 1

Rush W.
Rush W.

Reputation: 1361

var clothing = ['card0', 'card1', 'card2', 'card3'];
var timers = {}
var timerObj = {"startTime": null, "pauseTime": null, "elapsedTime": null, "hasSubmitted": false} //Nested object I want for all indices, will manipulate 0th index alone inside for loop

for (var i = 0; i < clothing.length; i++) {
  timers[i] = Object.assign({}, timerObj)
  if (i == 0) {
    timers[i]["startTime"] = Date.now();
  } 
} 
console.log(timers)

You can refer this for more information on this topic.

Upvotes: 1

Related Questions