Chr*_*ker 349 javascript
说我有一个对象:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
Run Code Online (Sandbox Code Playgroud)
我想用一个属性的子集创建一个新对象.
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
Run Code Online (Sandbox Code Playgroud)
我怎么能实现这个目标?
小智 560
使用对象解构和属性速记
const object = { a: 5, b: 6, c: 7 };
const picked = (({ a, c }) => ({ a, c }))(object);
console.log(picked); // { a: 5, c: 7 }
Run Code Online (Sandbox Code Playgroud)
来自Philipp Kewisch:
这实际上只是一个即时调用的匿名函数.所有这些都可以在MDN 上的Destructuring Assignment页面上找到.这是一个扩展的表格
let unwrap = ({a, c}) => ({a, c});
let unwrap2 = function({a, c}) { return { a, c }; };
let picked = unwrap({ a: 5, b: 6, c: 7 });
let picked2 = unwrap2({a: 5, b: 6, c: 7})
console.log(picked)
console.log(picked2)
Run Code Online (Sandbox Code Playgroud)
Ygg*_*Ygg 125
我建议看看Lodash ; 它有很多很棒的实用功能.
例如pick()
,你正是寻求的:
var subset = _.pick(elmo, ['color', 'height']);
Run Code Online (Sandbox Code Playgroud)
Lau*_*ren 86
如果您使用ES6,则可以使用destruct以非常简洁的方式执行此操作.Destructing允许您使用spread轻松添加对象,但它也允许您以相同的方式创建子集对象.
const object = {
a: 'a',
b: 'b',
c: 'c',
d: 'd',
}
// Remove "c" and "d" fields from original object:
const {c, d, ...partialObject} = object;
const subset = {c, d};
console.log(partialObject) // => { a: 'a', b: 'b'}
console.log(subset) // => { c: 'c', d: 'd'};
Run Code Online (Sandbox Code Playgroud)
Jos*_*bou 68
虽然它有点冗长,但是你可以通过使用Array.prototype.reduce来完成2年前其他人推荐使用下划线/ lodash的内容.
var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});
Run Code Online (Sandbox Code Playgroud)
这种方法从另一方面解决它:而不是获取一个对象并将属性名称传递给它来提取,获取一个属性名称数组并将它们减少为一个新对象.
虽然在最简单的情况下它更冗长,但这里的回调非常方便,因为您可以轻松满足一些常见要求,例如将"颜色"属性更改为新对象上的"颜色",展平数组等等.从一个服务/库接收对象并在其他地方构建新对象时需要执行的操作.虽然下划线/ lodash是优秀的,实现良好的库,但这是我更少的供应商依赖的首选方法,而当我的子集构建逻辑变得更复杂时,这是一种更简单,更一致的方法.
编辑:es7版本相同:
const subset = ['color', 'height'].reduce((a, e) => (a[e] = elmo[e], a), {});
Run Code Online (Sandbox Code Playgroud)
编辑:也是一个很好的例子!让'pick'函数返回另一个函数.
const pick = (...props) => o => props.reduce((a, e) => ({ ...a, [e]: o[e] }), {});
Run Code Online (Sandbox Code Playgroud)
上面的方法非常接近另一种方法,除了它可以让你动态构建一个"选择器".例如
pick('color', 'height')(elmo);
Run Code Online (Sandbox Code Playgroud)
这种方法特别简洁,你可以轻松地将所选择的"选择"传递给任何需要函数的东西,例如Array#map
:
[elmo, grover, bigBird].map(pick('color', 'height'));
// [
// { color: 'red', height: 'short' },
// { color: 'blue', height: 'medium' },
// { color: 'yellow', height: 'tall' },
// ]
Run Code Online (Sandbox Code Playgroud)
ale*_*lex 31
没有像核心库内置的内容,但你可以使用对象解构来做到这一点......
const {color, height} = sourceObject;
const newObject = {color, height};
Run Code Online (Sandbox Code Playgroud)
你也可以写一个实用功能吧...
const cloneAndPluck = function(sourceObject, keys) {
const newObject = {};
keys.forEach((obj, key) => { newObject[key] = sourceObject[key]; });
return newObject;
};
const subset = cloneAndPluck(elmo, ["color", "height"]);
Run Code Online (Sandbox Code Playgroud)
像Lodash这样的图书馆也有_.pick()
.
Cod*_*iac 25
我添加此答案是因为没有使用任何答案Comma operator
。
destructuring assignment
和,
操作符非常简单
const object = { a: 5, b: 6, c: 7 };
const picked = ({a,c} = object, {a,c})
console.log(picked);
Run Code Online (Sandbox Code Playgroud)
mpe*_*pen 21
打字稿解决方案:
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;
}
Run Code Online (Sandbox Code Playgroud)
键入信息甚至允许自动完成:
归功于绝对类型的U extends keyof T
技巧!
ied*_*mrc 20
我想提一提的是这里很不错的策展:
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
);
Run Code Online (Sandbox Code Playgroud)
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
Run Code Online (Sandbox Code Playgroud)
Object.keys(obj)
.filter((key) => ['whitelisted', 'keys'].indexOf(key) >= 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
Run Code Online (Sandbox Code Playgroud)
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
);
Run Code Online (Sandbox Code Playgroud)
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
Run Code Online (Sandbox Code Playgroud)
Object.keys(obj)
.filter((key) => ['blacklisted', 'keys'].indexOf(key) < 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
Run Code Online (Sandbox Code Playgroud)
Eve*_*ert 17
还有一个解决方案
var subset = {
color: elmo.color,
height: elmo.height
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这看起来比任何答案都要可读得多,但也许这就是我!
Est*_*ask 13
在每个JS版本中,任意选择的键列表的一线式都会变得更短:
Object.keys(obj)
.filter(function (key) {
return ['foo', 'bar'].indexOf(key) >= 0;
})
.reduce(function (obj2, key) {
obj2[key] = obj[key];
return obj2;
}, {});
Run Code Online (Sandbox Code Playgroud)
Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => Object.assign(obj2, { [key]: obj[key] }), {});
Run Code Online (Sandbox Code Playgroud)
或使用逗号运算符:
Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
Run Code Online (Sandbox Code Playgroud)
ECMAScript 2017具有Object.entries
和Array.prototype.includes
,ECMAScript 2019具有Object.fromEntries
,可以在需要时进行填充,使任务更轻松:
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
Run Code Online (Sandbox Code Playgroud)
可以将单行代码重写为类似于Lodash pick
/的帮助程序功能,omit
其中键列表通过参数传递:
const pick = (obj, ...keys) => Object.fromEntries(
Object.entries(obj)
.filter(([key]) => keys.includes(key))
);
pick(obj, 'foo', 'bar');
Run Code Online (Sandbox Code Playgroud)
Art*_*vim 10
你也可以使用Lodash.
var subset = _.pick(elmo ,'color', 'height');
Run Code Online (Sandbox Code Playgroud)
补充一下,假设你有一系列的"elmo":
elmos = [{
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
},{
color: 'blue',
annoying: true,
height: 'known',
meta: { one: '1', two: '2'}
},{
color: 'yellow',
annoying: false,
height: 'unknown',
meta: { one: '1', two: '2'}
}
];
Run Code Online (Sandbox Code Playgroud)
如果你想要相同的行为,使用lodash,你只需:
var subsets = _.map(elmos, function(elm) { return _.pick(elm, 'color', 'height'); });
Run Code Online (Sandbox Code Playgroud)
如本问题所述,在JavaScript中无法将结构化为动态命名的变量.
要动态设置键,可以使用reduce函数而不改变对象,如下所示:
const getSubset = (obj, ...keys) => keys.reduce((a, c) => ({ ...a, [c]: obj[c] }), {});
const elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
}
const subset = getSubset(elmo, 'color', 'annoying')
console.log(subset)
Run Code Online (Sandbox Code Playgroud)
['color', 'height'].reduce((a,b) => (a[b]=elmo[b],a), {})
Run Code Online (Sandbox Code Playgroud)
['color', 'height'].reduce((a,b) => (a[b]=elmo[b],a), {})
Run Code Online (Sandbox Code Playgroud)
我发现的最简单的方法(不会创建不必要的变量)是一个可以调用的函数,并且与 lodash 的工作方式相同,如下所示:
pick(obj, keys){
return Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}
Run Code Online (Sandbox Code Playgroud)
例如:
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)
Run Code Online (Sandbox Code Playgroud)
pick(obj, keys){
return Object.assign({}, ...keys.map(key => ({ [key]: obj[key] })))
}
Run Code Online (Sandbox Code Playgroud)
pick
lodash库的使用方法(如果已在使用)。
var obj = { 'a': 1, 'b': '2', 'c': 3 };
_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }
Run Code Online (Sandbox Code Playgroud)
https://lodash.com/docs/4.17.10#pick
还没有人演示过这种方法,可能是因为它很糟糕而且你不应该这样做,但我觉得它必须被列出来。
var o = {a:1,b:2,c:3,d:4,e:4,f:5}
with(o){
var output = {a,b,f}
}
console.log(output)
Run Code Online (Sandbox Code Playgroud)
优点:您不必输入两次属性名称。
缺点:出于多种原因,不推荐使用“ with ”语句。
结论:效果很好,但不要使用它。
小智 5
对象数组
const aListOfObjects = [{
prop1: 50,
prop2: "Nothing",
prop3: "hello",
prop4: "What's up",
},
{
prop1: 88,
prop2: "Whatever",
prop3: "world",
prop4: "You get it",
},
]
Run Code Online (Sandbox Code Playgroud)
通过以这种方式解构对象可以实现创建一个或多个对象的子集。
const sections = aListOfObjects.map(({prop1, prop2}) => ({prop1, prop2}));
Run Code Online (Sandbox Code Playgroud)