131

I wanted to add a key:value parameter to all the objects in an array.

eg:

var arrOfObj = [{name: 'eve'},{name:'john'},{name:'jane'}];

Now I wanted to add a new parameter, isActive to all the objects so the resulting array will look like.

eg:

 [{
 name: 'eve',
 isActive: true
}, {
 name: 'john',
 isActive: true
}, {
 name: 'jane',
 isActive: true
}]

I can always loop through the array and insert a key,value pair. But was wondering if there was a better way to do so

pinkfloydx33
13k3 gold badges54 silver badges70 bronze badges
asked Oct 3, 2016 at 8:10
3
  • 5
    arrOfObj.map(o => o.isActive = true;) Commented Oct 3, 2016 at 8:15
  • 12
    better would be arrOfObj.map(o => (o.isActive = true)); This would not throw no-return-assign error on ESLint and considered a best practice as well. Commented Jul 13, 2017 at 6:42
  • 1
    @redu it will not add to but replace the array with only [true,true,..]. Commented Sep 4, 2022 at 11:09

12 Answers 12

187

The map() function is a best choice for this case


tl;dr - Do this:

const newArr = [
 {name: 'eve'},
 {name: 'john'},
 {name: 'jane'}
].map(v => ({...v, isActive: true}))

The map() function won't modify the initial array, but creates a new one. This is also a good practice to keep initial array unmodified.


Alternatives:

const initialArr = [
 {name: 'eve'},
 {name: 'john'},
 {name: 'jane'}
 ]
const newArr1 = initialArr.map(v => ({...v, isActive: true}))
const newArr2 = initialArr.map(v => Object.assign(v, {isActive: true}))
// Results of newArr1 and newArr2 are the same

Add a key value pair conditionally

const arr = [{value: 1}, {value: 1}, {value: 2}] 
const newArr1 = arr.map(v => ({...v, isActive: v.value > 1}))

What if I don't want to add new field at all if the condition is false?

const arr = [{value: 1}, {value: 1}, {value: 2}] 
const newArr = arr.map(v => {
 return v.value > 1 ? {...v, isActive: true} : v 
})

Adding WITH modification of the initial array

const initialArr = [{a: 1}, {b: 2}]
initialArr.forEach(v => {v.isActive = true;});

This is probably not a best idea, but in a real life sometimes it's the only way.


Questions

  • Should I use a spread operator(...), or Object.assign and what's the difference?

Personally I prefer to use spread operator, because I think it uses much wider in modern web community (especially react's developers love it). But you can check the difference yourself: link(a bit opinionated and old, but still)

  • Can I use function keyword instead of =>?

Sure you can. The fat arrow (=>) functions play a bit different with this, but it's not so important for this particular case. But fat arrows function shorter and sometimes plays better as a callbacks. Therefore the usage of fat arrow functions is more modern approach.

  • What Actually happens inside map function: .map(v => ({...v, isActive: true})?

Map function iterates by array's elements and apply callback function for each of them. That callback function should return something that will become an element of a new array. We tell to the .map() function following: take current value(v which is an object), take all key-value pairs away from v andput it inside a new object({...v}), but also add property isActive and set it to true ({...v, isActive: true}) and then return the result. Btw, if original object contains isActive filed it will be overwritten. Object.assign works in a similar way.

  • Can I add more then one field at a time

Yes.

[{value: 1}, {value: 1}, {value: 2}].map(v => ({...v, isActive: true, howAreYou: 'good'}))
  • What I should not do inside .map() method

You shouldn't do any side effects[link 1, link 2], but apparently you can.

Also be noticed that map() iterates over each element of the array and apply function for each of them. So if you do some heavy stuff inside, you might be slow. This (a bit hacky) solution might be more productive in some cases (but I don't think you should apply it more then once in a lifetime).

  • Can I extract map's callback to a separate function?

Sure you can.

const arr = [{value: 1}, {value: 1}, {value: 2}] 
const newArr = arr.map(addIsActive)
function addIsActive(v) {
 return {...v, isActive: true}
}
  • What's wrong with old good for loop?

Nothing is wrong with for, you can still use it, it's just an old-school approach which is more verbose, less safe and mutate the initial array. But you can try:

const arr = [{a: 1}, {b: 2}]
for (let i = 0; i < arr.length; i++) {
 arr[i].isActive = true
}
  • What also i should learn

It would be smart to learn well following methods map(), filter(), reduce(), forEach(), and find(). These methods can solve 80% of what you usually want to do with arrays.

answered Oct 3, 2016 at 8:17
Sign up to request clarification or add additional context in comments.

2 Comments

return not necessary inside map function
"const initialArr = [ {name: 'eve'}, {name: 'john'}, {name: 'jane'} ] const newArr1 = initialArr.map(v => ({...v, isActive: true})) const newArr2 = initialArr.map(v => Object.assign({}, {isActive: true})) // Results of newArr1 and newArr2 are the same " This part is not right. newArr1 and newArr2 are not same. Please correct answer
124

You can do this with map()

var arrOfObj = [{
 name: 'eve'
}, {
 name: 'john'
}, {
 name: 'jane'
}];
var result = arrOfObj.map(function(o) {
 o.isActive = true;
 return o;
})
console.log(result)

If you want to keep original array you can clone objects with Object.assign()

var arrOfObj = [{
 name: 'eve'
}, {
 name: 'john'
}, {
 name: 'jane'
}];
var result = arrOfObj.map(function(el) {
 var o = Object.assign({}, el);
 o.isActive = true;
 return o;
})
console.log(arrOfObj);
console.log(result);

Cyril F
1,9022 gold badges19 silver badges39 bronze badges
answered Oct 3, 2016 at 8:16

3 Comments

return is unnecessary
@splay...In this case it is, since the result of map is being assigned to the result variable. It's more obvious also that map returns a new array (instead of using it as a throw away for each)
isn't map looping through the array in background?
21

I would be a little cautious with some of the answers presented in here, the following examples outputs differently according with the approach:

const list = [ { a : 'a', b : 'b' } , { a : 'a2' , b : 'b2' }]
console.log(list.map(item => item.c = 'c'))
// [ 'c', 'c' ]
console.log(list.map(item => {item.c = 'c'; return item;}))
// [ { a: 'a', b: 'b', c: 'c' }, { a: 'a2', b: 'b2', c: 'c' } ]
console.log(list.map(item => Object.assign({}, item, { c : 'c'})))
// [ { a: 'a', b: 'b', c: 'c' }, { a: 'a2', b: 'b2', c: 'c' } ]

I have used node v8.10.0 to test the above pieces of code.

answered Jun 8, 2018 at 19:03

1 Comment

These days, with all the new features node v8+ brings, using Object.assign is a very good and elegant option.
4

var arrOfObj = [{name: 'eve'},{name:'john'},{name:'jane'}];
const result = arrOfObj.map((name) => {
 name["isActive"] = true;
 return name;
});
console.log(result);

answered Feb 6, 2022 at 15:39

1 Comment

Thank you for this code snippet, which might provide some limited, immediate help. A proper explanation would greatly improve its long-term value by showing why this is a good solution to the problem and would make it more useful to future readers with other, similar questions. Please edit your answer to add some explanation, including the assumptions you’ve made.
2

You may also try this:

arrOfObj.forEach(function(item){item.isActive = true;});
console.log(arrOfObj);
answered Oct 3, 2016 at 8:19

Comments

2

@Redu's solution is a good solution

arrOfObj.map(o => o.isActive = true;) but Array.map still counts as looping through all items.

if you absolutely don't want to have any looping here's a dirty hack :

Object.defineProperty(Object.prototype, "isActive",{
 value: true,
 writable: true,
 configurable: true,
 enumerable: true
});

my advice is not to use it carefully though, it will patch absolutely all javascript Objects (Date, Array, Number, String or any other that inherit Object ) which is really bad practice...

answered Oct 3, 2016 at 9:13

1 Comment

o.isActive = true should either be o.isActive == true or just o.isActive
1
_.forEach(arrOfObj,(arrVal,arrIn) => {
 arrVal.isAcitve = true;
 }
answered Jan 24, 2021 at 2:51

Comments

1
let arrOfObj = [{name: 'eve'},{name:'john'},{name:'jane'}];
let newArr = arrOfObj.map(i => ({...i,isActive: true}));

Here what i did was i spread the current object and insert a new key with a value to the object and return it as a new object.

answered Jan 11, 2022 at 7:41

1 Comment

When posting an answer it is good to check existing answers and make your answer is unique.
0

Looping through the array and inserting a key, value pair is about your best solution. You could use the 'map' function but it is just a matter of preference.

var arrOfObj = [{name: 'eve'},{name:'john'},{name:'jane'}];
arrOfObj.map(function (obj) { 
 obj.isActive = true;
});
answered Oct 3, 2016 at 8:17

Comments

0

Simply use map function:

var arrOfObj = arrOfObj.map(function(element){
 element.active = true;
 return element;
}

Map is pretty decent on compatibility: you can be reasonably safe from IE <= 9.

However, if you are 100% sure your users will use ES6 Compatible browser, you can shorten that function with arrow functions, as @Sergey Panfilov has suggested.

answered Oct 3, 2016 at 8:17

2 Comments

Return is not necessary
@splay It is if you want to use .map() properly. You should be using .forEach() if you only want to use it as a loop.
0
 var arrOfObj = [{name: 'eve'},{name:'john'},{name:'jane'}];
 var injectObj = {isActive:true, timestamp:new Date()};
 // function to inject key values in all object of json array
 function injectKeyValueInArray (array, keyValues){
 return new Promise((resolve, reject) => {
 if (!array.length)
 return resolve(array);
 array.forEach((object) => {
 for (let key in keyValues) {
 object[key] = keyValues[key]
 }
 });
 resolve(array);
 })
 };
//call function to inject json key value in all array object
 injectKeyValueInArray(arrOfObj,injectObj).then((newArrOfObj)=>{
 console.log(newArrOfObj);
 });

Output like this:-

[ { name: 'eve',
 isActive: true,
 timestamp: 2017年12月16日T16:03:53.083Z },
 { name: 'john',
 isActive: true,
 timestamp: 2017年12月16日T16:03:53.083Z },
 { name: 'jane',
 isActive: true,
 timestamp: 2017年12月16日T16:03:53.083Z } ]
answered Dec 16, 2017 at 16:06

Comments

0

const arr = [{id: 1}, {id: 2}];
for (const obj of arr) {
 obj.color = 'red';
}
// 👇️ [ { id: 1, color: 'red' }, { id: 2, color: 'red' } ]
console.log(arr);

answered Jul 12, 2023 at 5:44

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.