假设我有一个对象:
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' }
我怎样才能做到呢?
当前回答
在这个问题中,解构为动态命名的变量在JavaScript中是不可能的。
要动态设置键,可以使用reduce函数而不改变对象,如下所示:
const get子集= (obj,…keys) =>个key。Reduce ((a, c) =>({…A, [c]: obj[c]}), {}); Const elmo = { 颜色:红色, 讨厌:没错, 高度:“未知”, Meta: {1: '1', 2: '2'} } const子集= get子集(elmo, 'color', '烦人') console.log(子集)
应该注意的是,你是在每次迭代中创建一个新对象,而不是更新一个克隆。——mpen
下面是一个使用reduce和单个克隆的版本(更新传入的初始值以reduce)。
const get子集= (obj,…keys) =>个key。Reduce ((acc, curr) => { Acc [curr] = obj[curr] 返回acc }, {}) Const elmo = { 颜色:红色, 讨厌:没错, 高度:“未知”, Meta: {1: '1', 2: '2'} } const子集= get子集(elmo, '烦人','height', 'meta') console.log(子集)
其他回答
function splice()
{
var ret = new Object();
for(i = 1; i < arguments.length; i++)
ret[arguments[i]] = arguments[0][arguments[i]];
return ret;
}
var answer = splice(elmo, "color", "height");
打印稿的解决方案:
function pick<T extends object, U extends keyof T>(
obj: T,
paths: Array<U>
): Pick<T, U> {
const ret = Object.create(null);
for (const k of paths) {
ret[k] = obj[k];
}
return ret;
}
输入信息甚至允许自动补全:
Credit to definitelytyping for U extends keyof T trick!
打印稿操场
虽然它有点啰嗦,但通过使用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' },
// ]
动态属性的解构赋值
这个解决方案不仅适用于你的具体例子,而且更普遍适用:
const subset2 = (x, y) = > ({[x]: [y]: b}) = > ({[x]: [y]: b}); const subset3 = (x, y, z) = > ({[x]: [y]: b [z]: c}) = > ({[x]: [y]: b [z]: c}); // const subset4… Const o = {a:1, b:2, c:3, d:4, e:5}; const pickBD = subset2("b", "d"); const pickACE = subset3("a", "c", "e"); console.log ( pickBD(o), // {b:2, d:4} pickACE(o) // {a:1, c:3, e:5} );
您可以轻松地定义subset4等,以考虑更多的属性。
如何:
function sliceObj(obj) {
var o = {}
, keys = [].slice.call(arguments, 1);
for (var i=0; i<keys.length; i++) {
if (keys[i] in obj) o[keys[i]] = obj[keys[i]];
}
return o;
}
var subset = sliceObj(elmo, 'color', 'height');