Javascript 将键值对添加到数组中的所有对象

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39827087/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 22:56:29  来源:igfitidea点击:

Add key value pair to all objects in array

javascriptarrays

提问by Shrujan Shetty

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

我想向数组中的所有对象添加一个 key:value 参数。

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.

现在我想向所有对象添加一个新参数 isActive ,以便生成的数组看起来像。

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

我总是可以遍历数组并插入一个键值对。但想知道是否有更好的方法来做到这一点

回答by Nenad Vracar

You can do this with map()

你可以这样做 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()

如果你想保留原始数组,你可以克隆对象 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);

回答by Sergei Panfilov

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

图()函数是这种情况下的最佳选择



tl;dr - Do this:

tl;dr - 这样做:

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

The map()function won't modifythe 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({}, {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 WITHmodification of the initial array

添加对初始数组的WITH修改

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.assignand what's the difference?
  • 我应该使用扩展运算符( ...),或者有Object.assign什么区别?

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)

我个人更喜欢使用 spread 运算符,因为我认为它在现代网络社区中使用范围更广(尤其是 react 的开发人员喜欢它)。但是你可以自己检查差异:链接(有点自以为是和旧的,但仍然)

  • Can I use functionkeyword instead of =>?
  • 我可以用function关键字代替=>吗?

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.

你当然可以。粗箭头 ( =>) 函数与 有点不同this,但对于这种特殊情况,它并不那么重要。但是胖箭头的功能更短,有时作为回调效果更好。因此,胖箭头函数的使用是更现代的方法。

  • What Actually happens inside map function: .map(v => ({...v, isActive: true})?
  • map函数内部实际发生了什么:.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(vwhich is an object), take all key-value pairs away from vandput it inside a new object({...v}), but also add property isActiveand set it to true ({...v, isActive: true}) and then return the result. Btw, if original object contains isActivefiled it will be overwritten. Object.assignworks in a similar way.

Map 函数按数组元素迭代并为每个元素应用回调函数。该回调函数应该返回一些将成为新数组元素的东西。我们告诉.map()函数如下:取当前值(v它是一个对象),取出所有键值对v并将其放入一个新对象({...v})中,同时添加属性isActive并将其设置为true({...v, isActive: true})然后返回结果. 顺便说一句,如果原始对象包含isActive归档,它将被覆盖。Object.assign以类似的方式工作。

  • 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
  • 我不应该在.map()方法里面做什么

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

你不应该做任何副作用[link 1, link 2],但显然你可以。

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) solutionmight be more productive in some cases (but I don't think you should apply it more then once in a lifetime).

还要注意,map()迭代数组的每个元素并为每个元素应用函数。所以如果你在里面做一些重的事情,你可能会很慢。在某些情况下,这个(有点 hacky)解决方案可能更有效率(但我认为您一生中不应多次应用它)。

  • 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?
  • 旧的 good for 循环有什么问题?

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:

没有什么问题for,你仍然可以使用它,它只是一种老式的方法,它更冗长,安全性更低,并且会改变初始数组。但是你可以试试:

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.

按照map()filter()reduce()forEach()find()方法学习会很聪明。这些方法可以解决你通常想要用数组做的事情的 80%。

回答by MarcoSantana

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.0to test the above pieces of code.

我已经使用node v8.10.0来测试上面的代码片段。

回答by Umar Tariq

Simply you can add that way. see below the console image

你可以简单地添加这种方式。请参阅下面的控制台图像

enter image description here

在此处输入图片说明

回答by user2173403

@Redu's solution is a good solution

@Redu 的解决方案是一个很好的解决方案

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

arrOfObj.map(o => o.isActive = true;) 但 Array.map 仍然算作遍历所有项目。

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...

我的建议是不要小心地使用它,它绝对会修补所有 javascript 对象(日期、数组、数字、字符串或任何其他继承 Object 的对象),这是非常糟糕的做法......

回答by Dhananjaya Kuppu

You may also try this:

你也可以试试这个:

arrOfObj.forEach(function(item){item.isActive = true;});

console.log(arrOfObj);

回答by Sayed Tauseef Haider Naqvi

    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-16T16:03:53.083Z },
  { name: 'john',
    isActive: true,
    timestamp: 2017-12-16T16:03:53.083Z },
  { name: 'jane',
    isActive: true,
    timestamp: 2017-12-16T16:03:53.083Z } ]

回答by splay

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;
});

回答by Luxor001

Simply use mapfunction:

只需使用地图功能:

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.

Map 在兼容性方面相当不错:您可以相当安全地远离 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.

但是,如果您 100% 确定您的用户将使用兼容 ES6 的浏览器,您可以使用箭头函数缩短该功能,正如@Sergey Panfilov 所建议的那样。

回答by Andrew Koper

arrOfObj.map(o => { 
  o.isActive = true; 
  return o; 
});