我有一些代码基本上需要一个对象数组,只是为每个项添加一个额外的键。我希望能够尽可能简洁地表达这一点作为实验。
{
"size": 0,
"aggs": {
"unique_ids": {
"terms": {
"field": "campaign_id",
"size": 10
},
"aggs": {
"one_value": {
"max": {
"field": "clicks"
}
}
}
},
"sum_uniques": {
"sum_bucket": {
"buckets_path": "unique_ids>one_value"
}
}
}
}
目前,这是有效的,但它当然没有任何一个班轮,let fruits = [
{"type" : "orange"},
{"type" : "apple"},
{"type" : "banana"}
];
console.log(fruits.map((fruit) => {
fruit.price = "$1.00";
return fruit;
}));
声明仍在那里,我觉得有一种方法可以摆脱它,因为胖箭语法。
答案 0 :(得分:3)
一种方法是使用Object.assign扩展对象并返回生成的新对象:
console.log(fruits.map(fruit => Object.assign(fruit, { price: "1.00" })));
这消除了对return
关键字的需求,但它并不是最大的节省空间。它也等同于你已经拥有的东西(因为原来的fruit
对象被修改了。正如joews指出的那样,如果你想保留原始数组,你可以使用一个空的目标对象,如下所示:
Object.assign({}, fruit, { price: "1.00"});
这将确保您的原始数组未经修改(可能是您想要的也可能不是。)
答案 1 :(得分:3)
如果您不需要.forEach()
.map()
代替fruits
直接修改fruits
fruits.forEach((fruit) => fruit.price = "$1.00");
答案 2 :(得分:2)
可以做这样的事情,不推荐用于可读性,但技术上是一行。
fruits.map(fruit => (fruit.price = "$1.00") && fruit);
正如其他人提到的那样,这个方法只是为对象添加一个属性而不复制它。将此作为一个简单的方法,使用地图并实际创建副本的简单方法是:
fruits.map(fruit => Object.assign({price: "$1.00"}, fruit));
Object.assign()
会将fruit
的所有属性分配给对象{ price: "$1.00" }
并将其返回。
实例:
"use strict";
let log = function() {
output.textContent += [].join.call(arguments, ' ') + '\n\n';
};
log('# MAP (OR FOREACH) WITHOUT ASSIGN');
let fruits = [
{"type" : "orange"},
{"type" : "apple"},
{"type" : "banana"}
];
let newfruits = fruits.map(fruit => (fruit.price = "$1.00") && fruit);
log('fruits', JSON.stringify(fruits));
log('newfruits', JSON.stringify(newfruits));
log('^-- Both are modified since newfruits its a new array with the same objects');
log('# MAP WITH ASSIGN');
fruits = [
{"type" : "orange"},
{"type" : "apple"},
{"type" : "banana"}
];
newfruits = fruits.map(fruit => Object.assign({price: "$1.00"}, fruit));
log('fruits', JSON.stringify(fruits));
log('newfruits', JSON.stringify(newfruits));
log('^-- Only newfruits is modified since its a new array with new objects');

pre {
word-wrap: break-word;
}

<pre id="output"></pre>
&#13;
答案 3 :(得分:1)
有很多方法可以做到这一点:
如果你想内联你可以使用逗号运算符(虽然它有点模糊):
fruits.map((fruit) => (fruit.price = "$1.00", fruit))
我们也可以使用&&
,因为赋值会返回指定的值,"$1.00"
是真实的,但逗号运算符更通用,因为我们也可以设置false
或0
让一切继续发挥作用。
然而,制作辅助函数可能更好:
// We're currying manually here, but you could also make the signature
// setter(name, value) and use your function of choice to curry when you need to.
function setter(name) {
return (value) => (obj) => {
obj[name] = value;
return obj;
}
}
然后你可以使用:
fruits.map(setter("price")("$1.00"))
正如@Suppen在评论中指出的那样,因为普通的JavaScript对象是可变的,所以您也可以避免使用map
并使用forEach
代替:
fruits.forEach(fruit => fruit.price = "$1.00");
// Each element in fruits has been modified in-place.
答案 4 :(得分:0)
映射函数几乎总是纯粹的。如果您只想修改对象,一个简单的循环会做得更好(for (let fruit of fruits) fruit.price = …; console.log(fruits);
)。
因此,当您返回一个新对象时,单行会很容易:
console.log(fruits.map(({type}) => ({type, price:"$1.00"})));
如果你有很多属性或属性你不知道,那么Object.assign({}, …)
就是你的朋友(就像@ joews&#39;评论@RGraham&#39的答案)