说我有一个对象:
elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
我想用一个属性的子集创建一个新对象。
// pseudo code
subset = elmo.slice('color', 'height')
//=> { color: 'red', height: 'unknown' }
我怎么能实现这个目标?
答案 0 :(得分:451)
使用对象解构和属性简写
const object = { a: 5, b: 6, c: 7 };
const picked = (({ a, c }) => ({ a, c }))(object);
console.log(picked); // { a: 5, c: 7 }

来自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)

答案 1 :(得分:104)
答案 2 :(得分:71)
如果您正在使用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'};
答案 3 :(得分:55)
虽然它有点冗长,但是通过使用Array.prototype.reduce,你可以完成2年前其他人推荐使用下划线/ lodash的内容。
var subset = ['color', 'height'].reduce(function(o, k) { o[k] = elmo[k]; return o; }, {});
这种方法从另一方面解决了这个问题:不是拿一个对象并将属性名称传递给它来提取,而是取一个属性名称数组并将它们缩减为一个新对象。
虽然在最简单的情况下它更加冗长,但这里的回调非常方便,因为您可以轻松满足一些常见要求,例如:将'color'属性更改为新对象上的'color',展平数组等 - 从一个服务/库接收对象并在其他地方构建新对象时需要执行的任何操作。虽然下划线/ lodash是优秀的,良好实现的库,但这是我更少的供应商依赖的首选方法,而当我的子集构建逻辑变得更复杂时,这是一种更简单,更一致的方法。
编辑: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] }), {});
以上与其他方法非常接近,只是它可以让你动态构建一个“选择器”。 e.g。
pick('color', 'height')(elmo);
这种方法特别简洁,你可以很容易地将所选择的“选择”传递给任何需要功能的东西,例如: Array#map
:
[elmo, grover, bigBird].map(pick('color', 'height'));
// [
// { color: 'red', height: 'short' },
// { color: 'blue', height: 'medium' },
// { color: 'yellow', height: 'tall' },
// ]
答案 4 :(得分:25)
核心库中没有内置的东西,但你可以使用对象解构来实现它......
const {color, height} = sourceObject;
const newObject = {color, height};
您还可以编写实用程序功能吗...
const cloneAndPluck = function(sourceObject, keys) {
const newObject = {};
keys.forEach((obj, key) => { newObject[key] = sourceObject[key]; });
return newObject;
};
const subset = cloneAndPluck(elmo, ["color", "height"]);
Lodash等图书馆也有_.pick()
。
答案 5 :(得分:11)
我想在这里提到that很好的策展:
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
);
Object.entries(obj)
.filter(([key]) => ['whitelisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
Object.keys(obj)
.filter((key) => ['whitelisted', 'keys'].indexOf(key) >= 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
);
Object.entries(obj)
.filter(([key]) => !['blacklisted', 'keys'].includes(key))
.reduce((obj, [key, val]) => Object.assign(obj, { [key]: val }), {});
Object.keys(obj)
.filter((key) => ['blacklisted', 'keys'].indexOf(key) < 0)
.reduce((newObj, key) => Object.assign(newObj, { [key]: obj[key] }), {})
答案 6 :(得分:10)
我添加此答案是因为没有答案使用Comma operator
。
使用destructuring assignment和,
运算符非常简单
const object = { a: 5, b: 6, c: 7 };
const picked = ({a,c} = object, {a,c})
console.log(picked); // { a: 5, c: 7 }
答案 7 :(得分:9)
您也可以使用Lodash。
var subset = _.pick(elmo ,'color', 'height');
补充一下,假设你有一系列“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'}
}
];
如果你想要相同的行为,使用lodash,你只需:
var subsets = _.map(elmos, function(elm) { return _.pick(elm, 'color', 'height'); });
答案 8 :(得分:9)
还有一个解决方案:
var subset = {
color: elmo.color,
height: elmo.height
}
到目前为止,这看起来比任何答案都要可读得多,但也许只是我!
答案 9 :(得分:8)
如JavaScript question中所述,在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)
&#13;
应注意,您在每次迭代时都创建了一个新对象,而不是更新单个克隆。 - mpen
下面是使用reduce with single clone的版本(更新传入的初始值为reduce)。
const getSubset = (obj, ...keys) => keys.reduce((acc, curr) => {
acc[curr] = obj[curr]
return acc
}, {})
const elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
}
const subset = getSubset(elmo, 'annoying', 'height', 'meta')
console.log(subset)
&#13;
答案 10 :(得分:4)
另一种方式......
var elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
}
var subset = [elmo].map(x => ({
color: x.color,
height: x.height
}))[0]
您可以将此函数与Objects =)
数组一起使用答案 11 :(得分:4)
如果已经使用lodash库,请使用pick
方法。
var obj = { 'a': 1, 'b': '2', 'c': 3 };
_.pick(object, ['a', 'c']);
// => { 'a': 1, 'c': 3 }
答案 12 :(得分:2)
到目前为止,还没有人演示这种方法,可能是因为它很糟糕,您不应该这样做,但是我觉得必须列出它。
var o = {a:1,b:2,c:3,d:4,e:4,f:5}
with(o){
var output = {a,b,f}
}
console.log(output)
专业人士:您不必两次输入属性名称。
缺点:由于许多原因,不建议使用“ with”语句。
结论:它很好用,但不要使用。
答案 13 :(得分:2)
在每个JS版本中,任意选择的键列表的一线式都会变得更短:
Object.keys(obj)
.filter(function (key) {
return ['foo', 'bar'].indexOf(key) >= 0;
})
.reduce(function (obj2, key) {
obj2[key] = obj[key];
return obj2;
}, {});
Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => Object.assign(obj2, { [key]: obj[key] }), {});
或使用逗号运算符:
Object.keys(obj)
.filter(key => ['foo', 'bar'].indexOf(key) >= 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
ECMAScript 2017具有Object.entries
和Array.prototype.includes
,ECMAScript 2019具有Object.fromEntries
,可以在需要时对其进行填充,从而使任务更容易:
Object.fromEntries(
Object.entries(obj)
.filter(([key]) => ['foo', 'bar'].includes(key))
)
答案 14 :(得分:2)
这适用于Chrome控制台。这有什么问题吗?
var { color, height } = elmo
var subelmo = { color, height }
console.log(subelmo) // {color: "red", height: "unknown"}
答案 15 :(得分:2)
要添加另一种深奥的方法,这也可以:
var obj = {a: 1, b:2, c:3}
var newobj = {a,c}=obj && {a,c}
// {a: 1, c:3}
但是您必须写两次道具名称。
答案 16 :(得分:1)
这是Node.js的完整解决方案
>>> npm i --save lodash.pick
var pick = require('lodash.pick');
var user = {name: 'Bill', number:'1', age:'10'}
var subset = pick(user, ['name', 'number']);
答案 17 :(得分:1)
我遇到了同样的问题,可以使用以下库轻松解决它:
https://www.npmjs.com/package/object.pick
pick({a: 'a', b: 'b', c: 'c'}, ['a', 'b'])
//=> {a: 'a', b: 'b'}
https://www.npmjs.com/package/object.omit
omit({a: 'a', b: 'b', c: 'c'}, ['a', 'c'])
//=> { b: 'b' }
答案 18 :(得分:1)
动态解决方案
['color', 'height'].reduce((a,b) => (a[b]=elmo[b],a), {})
let elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
let subset= ['color', 'height'].reduce((a,b)=> (a[b]=elmo[b],a),{});
console.log( subset );
答案 19 :(得分:1)
此解决方案不仅适用于您的具体示例,而且更为普遍适用:
const subset2 = (x, y) => ({[x]:a, [y]:b}) => ({[x]:a, [y]:b});
const subset3 = (x, y, z) => ({[x]:a, [y]:b, [z]:c}) => ({[x]:a, [y]:b, [z]:c});
// const subset4...etc.
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}
);
&#13;
您可以轻松定义subset4
等,以考虑更多属性。
答案 20 :(得分:1)
将参数转换为数组
使用Array.forEach()
选择属性
Object.prototype.pick = function(...args) {
var obj = {};
args.forEach(k => obj[k] = this[k])
return obj
}
var a = {0:"a",1:"b",2:"c"}
var b = a.pick('1','2') //output will be {1: "b", 2: "c"}
答案 21 :(得分:1)
我发现的最简单的方法(不会创建不必要的变量)是一个可以调用的函数,并且与 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) => {
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)
答案 22 :(得分:1)
怎么样:
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');
答案 23 :(得分:0)
对象数组
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})
答案 24 :(得分:0)
像这个线程上的几个一样,我同意最明显的老派方法实际上是最好的,但是为了好玩,让我在某些情况下提供另一种不明智的方法,比如当你已经有了您的子集已定义,并且您希望从另一个包含超集或相交属性集的对象向其复制属性。
let set = { a : 1, b : 2, c : 3 };
let subset = { a : null, b : null };
try {
Object.assign(Object.seal(subset), set);
} catch (e) {
console.log('its ok I meant to do that <(^.^)^');
}
console.log(subset);
答案 25 :(得分:0)
将我的2美分加到Ivan Nosov答案中:
在我的情况下,我需要从对象中“切出”许多键,因此它变得非常丑陋,而且不是一种动态解决方案:
fibonacci.js
这是使用eval的动态解决方案:
const object = { a: 5, b: 6, c: 7, d: 8, aa: 5, bb: 6, cc: 7, dd: 8, aaa: 5, bbb: 6, ccc: 7, ddd: 8, ab: 5, bc: 6, cd: 7, de: 8 };
const picked = (({ a, aa, aaa, ab, c, cc, ccc, cd }) => ({ a, aa, aaa, ab, c, cc, ccc, cd }))(object);
console.log(picked);
答案 26 :(得分:0)
TypeScript解决方案:
export function pick<T extends object, U extends keyof T>(obj: T, paths: Array<U>) {
return paths.reduce((o, k) => {
o[k] = obj[k];
return o;
}, Object.create(null));
}
键入信息甚至可以自动完成:
为U extends keyof T
技巧获得DefinitelyTyped的奖励!
答案 27 :(得分:0)
尝试
const elmo={color:"red",annoying:!0,height:"unknown",meta:{one:"1",two:"2"}};
const {color, height} = elmo; newObject = ({color, height});
console.log(newObject); //{ color: 'red', height: 'unknown' }
答案 28 :(得分:0)
古老的Array.prototype.reduce
:
const selectable = {a: null, b: null};
const v = {a: true, b: 'yes', c: 4};
const r = Object.keys(selectable).reduce((a, b) => {
return (a[b] = v[b]), a;
}, {});
console.log(r);
这个答案使用了神奇的逗号运算符,同时: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Comma_Operator
如果你想变得更加精致,那就更紧凑了:
const r = Object.keys(selectable).reduce((a, b) => (a[b] = v[b], a), {});
将所有内容整合到一个可重用的功能中:
const getSelectable = function (selectable, original) {
return Object.keys(selectable).reduce((a, b) => (a[b] = original[b], a), {})
};
const r = getSelectable(selectable, v);
console.log(r);
答案 29 :(得分:0)
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");
答案 30 :(得分:-2)
注意:虽然问的原始问题是javascript,但它可以 通过以下解决方案完成jQuery
如果你想要的话,可以扩展jquery是一个切片的示例代码:
jQuery.extend({
sliceMe: function(obj, str) {
var returnJsonObj = null;
$.each( obj, function(name, value){
alert("name: "+name+", value: "+value);
if(name==str){
returnJsonObj = JSON.stringify("{"+name+":"+value+"}");
}
});
return returnJsonObj;
}
});
var elmo = {
color: 'red',
annoying: true,
height: 'unknown',
meta: { one: '1', two: '2'}
};
var temp = $.sliceMe(elmo,"color");
alert(JSON.stringify(temp));
这是相同的小提琴:http://jsfiddle.net/w633z/