0

I am trying to loop through an Array of Objects, modify each Object, and push the result into a new Array.

The Objects in the array have different values. When I examine the resulting Array all of the Objects all have the same value. They all reflect the last Object in the original Array

For Example:

const a = { choo: 'choo' }
const b = [ { foo: 'bar' }, { foo: 'baz' }, { foo: 'foo' } ]

let c = [];
b.forEach((item) => {
  c.push(Object.assign(a, {...item} ));
});

The result of c:

[ 
  { foo: 'foo', choo: 'choo' }, 
  { foo: 'foo', choo: 'choo' }, 
  { foo: 'foo', choo: 'choo' } 
]

I assume this is some sort of scope issue but I'm not sure how to fix it.

Expected results would be

[
  { foo: 'bar', choo: 'choo' }, 
  { foo: 'baz', choo: 'choo' }, 
  { foo: 'foo', choo: 'choo' } 
]

5 Answers 5

4

I am trying to loop through an Array of Objects, modify each Object, and push the result into a new Array.

Sounds like what you want is .map, not .forEach.

When I examine the resulting Array all of the Objects all have the same value. They all reflect the last Object in the original Array

This is because Object.assign modifies an object. You are modifying a several times and creating an array with several references to a.

The answer is to pass an empty object as the first argument to Object.assign (and use map). The use of {...item} is also meaningless, so I have replaced that with item:

const a = { choo: 'choo' }
const b = [ { foo: 'bar' }, { foo: 'baz' }, { foo: 'foo' } ]

const c = b.map((item) => Object.assign({}, a, item));

console.log(c);

Edit: If you actually do want to modify the original objects, you can do that by changing the order of the arguments to Object.assign so that item is first. I would not recommend this though:

const a = { choo: 'choo' }
const b = [ { foo: 'bar' }, { foo: 'baz' }, { foo: 'foo' } ]

const c = b.map((item) => Object.assign(item, a));

console.log(c);
console.log(b);

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

2 Comments

That doesn't mutate the original object though, and he said he did want to modify it.
@CertainPerformance I'm guessing that OP just used a poor choice of words there, but fair enough. I've added an addendum.
1

Yes, that's how Object.assign works: it modifies the target and returns it, it does not create a new object. All your results reference the a that you passed as the target.

You're looking for

const c = b.map(item => ({...a, ...item})); // with object spread syntax

or

const c = b.map(item => Object.assign({}, a, item)); // with Object.assign

Comments

0
b.forEach((item) => {
  c.push(Object.assign(a, {...item} ));
});

Not {...b}, must be {...item}

1 Comment

Sorry, simplified my code for the question, I am using {...item}. I have updated the question
0

The problem is your {...b} - you're copying all properties of objects in b, when you only want to copy the property of the item you're iterating over.

const a = { choo: 'choo' }
const b = [ { foo: 'bar' }, { foo: 'baz' }, { foo: 'foo' } ]
const c = [];
b.forEach((item) => {
  c.push(Object.assign(item, a));
});
console.log(c);

You also want the first parameter of Object.assign to be the object you're mutating.

Comments

0

Object.assign, this function will make your object a changed, and return the reference of object a.

That means, you change the object a and push its reference to array c in each loop.

Finally, you will get the array c which includes three references of object a. This moment, a is { foo: 'foo', choo: 'choo' } .

HOW TO SOLVE?

The key is, push the different reference to array c in each loop.

const a = { choo: 'choo' }
const b = [ { foo: 'bar' }, { foo: 'baz' }, { foo: 'foo' } ]

let c = [];
b.forEach((item) => {
  c.push(Object.assign({}, a, item ));
});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.