假设我有一个对象:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
我想用它的属性子集创建一个新对象。
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
我怎样才能做到呢?
假设我有一个对象:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
我想用它的属性子集创建一个新对象。
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
我怎样才能做到呢?
当前回答
我想在这里提到一个非常好的策展:
pick-es2019.js
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
);
pick-es2017.js
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
pick-es2015.js
Object.keys(obj)
.filter((key) => ['whitelisted', 'keys'].indexOf(key) >= 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
omit-es2019.js
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
);
omit-es2017.js
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
omit-es2015.js
Object.keys(obj)
.filter((key) => ['blacklisted', 'keys'].indexOf(key) < 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
其他回答
对象数组
const aListOfObjects = [{
prop1: 50,
prop2: "Nothing",
prop3: "hello",
prop4: "What's up",
},
{
prop1: 88,
prop2: "Whatever",
prop3: "world",
prop4: "You get it",
},
]
创建一个或多个对象的子集可以通过这种方式解构对象来实现。
const sections = aListOfObjects.map(({prop1, prop2}) => ({prop1, prop2}));
虽然它有点啰嗦,但通过使用Array.prototype.reduce,你可以完成其他人在2年前推荐的underscore/lodash。
var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});
这种方法从另一方面解决了这个问题:而不是获取一个对象并将属性名传递给它来提取,而是获取一个属性名数组并将它们简化为一个新对象。
While it's more verbose in the simplest case, a callback here is pretty handy, since you can easily meet some common requirements, e.g. change the 'color' property to 'colour' on the new object, flatten arrays, etc. -- any of the things you need to do when receiving an object from one service/library and building a new object needed somewhere else. While underscore/lodash are excellent, well-implemented libs, this is my preferred approach for less vendor-reliance, and a simpler, more consistent approach when my subset-building logic gets more complex.
编辑:es7版本相同:
const subset = ['color', 'height'].reduce((a, e) => (a[e] = elmo[e], a), {});
编辑:这也是咖喱的一个很好的例子!让'pick'函数返回另一个函数。
const pick = (...props) => o => props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});
上面的方法非常接近于另一种方法,除了它让你在运行中构建一个“picker”。如。
pick('color', 'height')(elmo);
这种方法的特别之处在于,你可以很容易地将所选的“picks”传递到任何带有函数的对象中,例如Array#map:
[elmo, grover, bigBird].map(pick('color', 'height'));
// [
// { color: 'red', height: 'short' },
// { color: 'blue', height: 'medium' },
// { color: 'yellow', height: 'tall' },
// ]
还有一个解决方案:
var subset = {
color: elmo.color,
height: elmo.height
}
到目前为止,这看起来比任何答案都更具可读性,但也许这只是我的想法!
我发现最简单的方法,它不会创建不必要的变量,是一个函数,你可以调用,工作原理与lodash相同,如下所示:
pick(obj, keys){
return Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}
例如:
pick(obj, keys){
return Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}
const obj = {a:1, b:2, c:3, d:4}
const keys = ['a', 'c', 'f']
const picked = pick(obj,keys)
console.log(picked)
Pick = (obj, keys) => { 返回对象。分配({},…键。Map (key => ({ (例子):obj(例子) }))) } Const obj = { 答:1, b: 2 c: 3, d: 4 } Const keys = ['a', 'c', 'f'] Const selected = pick(obj, keys) console.log(选)
扩展内置原型有其优势。如果你使用Object.defineProperty,你不会产生任何污染-唯一剩下的问题是与未来属性的冲突(例如,你定义Object.prototype。在将来,ES标准将Object.prototype.slice定义为具有不同的功能-现在您的代码正在破坏Object.prototype.slice中应该存在的预期功能)。
...... ....... ...... .....Elmo的身高不是未知的(!!)
Object.defineProperty(Object.prototype, 'slice', { 可列举的:假的, 可写:没错, 值:function(…args) { 让o = {}; for (let k of args) this. hasownproperty (k) && (o[k] = this[k]); 返回啊; } }); Elmo = { 颜色:红色, 讨厌:没错, 高度:“24”, Meta: {1: '1', 2: '2'} }; console.log(艾尔摩。片(“颜色”、“高度”)); console.log('看,没有污染:); 对于(let k in elmo) console.log(' - ${k} ');