3

I'm trying to do a single loop and update an object property with each loop value but something unexpected happens:

The first console.log prints the day object property updated as expected. The second one, however, which prints the full object, shows the day property with the value of the final forEach value.

Example: data.days = [ 5, 6 ]

First loop prints:

newData.date: 5
{prop1: x, prop2: x...., date: 6}

Second loop prints:

newData.date: 6
{prop1: x, prop2: x...., date: 6}

This is the my code:

data.days.forEach(day => {
    let newData;
    newData = data.data;
    newData.date = day;
    console.log('newData.date: ' + newData.date)
    console.log(newData)
})

I've tried to create the newData variable out of forEach or a for loop instead, but I have the same result.

4
  • 1
    data.days = { 5, 6 } is invalid syntax Commented May 23, 2019 at 15:03
  • As Maheer Ali tolds you : forEach works on Arrays and data.days is ... Commented May 23, 2019 at 15:05
  • newData = data.data is copy by reference, you're actually assigning the same object on every loop. That's why you always get the last value in the final loop... Commented May 23, 2019 at 15:18
  • data.days is declared as an empty array and the values are pushed or spliced as i need before to call the loop. In fact, it's printing the correct value in each loop as you can see in the first console.log Commented May 23, 2019 at 15:31

4 Answers 4

3

The issue you are seeing is caused by the fact that the browser console, in an attempt to be very helpful, is not logging a string when you log an object. Instead, it's logging a live view of that object. Therefore, if you log the object and then update it, you will see the updated version in the console. However, when you log the property of the object, the console logs it as a static string.

You can see this here:

enter image description here

The string is just logged as a static string, but the object is treated specially, with syntax highlighting and expanding property views and such.

Here's an example where we log the static stringified version of the object instead as well as the dynamic reference to the object:

let days = [5, 6];
let newData = {};

days.forEach(day => {
    newData.date = day;
    console.log('newData.date: ' + newData.date);
    console.log(JSON.stringify(newData));
    console.log(newData);
});

This yields:

enter image description here

Sign up to request clarification or add additional context in comments.

2 Comments

It have sense, but now i have a new problem: i need to do a post request in each loop. It would create a new register with a different date value but instead it creates as many registers as array length but all with the last loop value.
@KenRamirez I'm not sure exactly what is happening, but it sounds like you may be running into issues with the fact that post requests are asynchronous, so the slight delay means it's sending the final version. What if you used JSON.stringify in the loop to send your data? It gets stringified anyway as part of the request process.
1

Your issue is here:

...
let newData;
newData = data.data;
...

You're not creating a new object with newData variable, instead you're just referencing the same data.data object into it on each iteration. This is why the final newData value will always be what is sets on the last loop iteration.

If want a new distinct object for each loop, you need to (deep) clone/ copy the data.data instead of just referencing it:

var data = {};
data.data = { prop1: 'x', prop2: 'x' };
data.days = [ 5, 6 ];

data.days.forEach(day => {
    let newData;
    newData = Object.assign({}, data.data); 
    newData.date = day;
    console.log('newData.date: ' + newData.date)
    console.log(newData)
});

Note: Object.assign does shallow copy of an object, you need to resort to something else if need to deep copy the object.

Comments

0

Objects don't have forEach method (it's mainly for Arrays) but you can iterate on their properties with for (let prop in object).

In your example:

for (let day in data.days) {
    // Do your stuff
}

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in

2 Comments

As i said, i've try with "for" loop but i get the same result. The console shows correctly the for or foreach object value, even the object propertie as updated, but when i want to print the full object after being updated, the updated propertie shows the LAST value of the forEach
Oh, I think it's because the value of newData is updated each loop but not saved. You can declare it outside of the for scope as an Array and push each day's value into it.
0

According to ECMAScript documentation, a link

at 22.1.3.12 Array.prototype.forEach ( callbackfn [ , thisArg ] )

callbackfn should be a function that accepts three arguments. forEach calls callbackfn once for each element present in the array, in ascending order. callbackfn is called only for elements of the array which actually exist; it is not called for missing elements of the array.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.