假设我有一个对象:
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] }), {})
其他回答
补充另一种深奥的方法,这也很有效:
var obj = {a: 1, b:2, c:3}
var newobj = {a,c}=obj && {a,c}
// {a: 1, c:3}
但是你必须把道具名写两遍。
注意:虽然最初的问题是针对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/
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");
两种常见的方法是解构和传统的类似lodash的选择/省略实现。它们之间的主要实际区别是,解构需要一个键列表是静态的,不能省略它们,包括不存在的选择键,即它是包含的。这可能是可取的,也可能是不可取的,并且不能为析构语法而更改。
考虑到:
var obj = { 'foo-bar': 1, bar: 2, qux: 3 };
定期选择foo-bar, bar, baz键的预期结果:
{ 'foo-bar': 1, bar: 2 }
包容性挑选的预期结果:
{ 'foo-bar': 1, bar: 2, baz: undefined }
解构
析构语法允许用函数参数或变量对对象进行解构和重组。
限制在于键的列表是预定义的,它们不能像问题中描述的那样被列为字符串。如果键是非字母数字,例如foo-bar,则析构将变得更加复杂。
优点是它的性能解决方案对ES6来说是很自然的。
缺点是键的列表是重复的,在列表很长的情况下,这会导致冗长的代码。由于在这种情况下解构会重复对象文字语法,因此可以原样复制和粘贴列表。
IIFE
const subset = (({ 'foo-bar': foo, bar, baz }) => ({ 'foo-bar': foo, bar, baz }))(obj);
临时变量
const { 'foo-bar': foo, bar, baz } = obj;
const subset = { 'foo-bar': foo, bar, baz };
字符串列表
任意选择的键列表由字符串组成,如问题所要求的。这允许不预定义它们,并使用包含键名的变量,['foo-bar', someKey,…moreKeys]。
ECMAScript 2017有Object。entry和Array.prototype。包括,ECMAScript 2019有object . fromentry,它们可以在需要时填充。
一行程序
考虑到要选择的对象包含额外的键,通常从列表中迭代键比从对象键更有效,如果需要省略键,反之亦然。
Pick (ES5)
var subset = ['foo-bar', 'bar', 'baz']
.reduce(function (obj2, key) {
if (key in obj) // line can be removed to make it inclusive
obj2[key] = obj[key];
return obj2;
}, {});
自己的 (ES5)
var subset = Object.keys(obj)
.filter(function (key) {
return ['baz', 'qux'].indexOf(key) < 0;
})
.reduce(function (obj2, key) {
obj2[key] = obj[key];
return obj2;
}, {});
拾取 (ES6)
const subset = ['foo-bar', 'bar', 'baz']
.filter(key => key in obj) // line can be removed to make it inclusive
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
省略 (ES6)
const subset = Object.keys(obj)
.filter(key => ['baz', 'qux'].indexOf(key) < 0)
.reduce((obj2, key) => (obj2[key] = obj[key], obj2), {});
挑选 (ES2019)
const subset = Object.fromEntries(
['foo-bar', 'bar', 'baz']
.filter(key => key in obj) // line can be removed to make it inclusive
.map(key => [key, obj[key]])
);
省略 (ES2019)
const subset = Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !['baz', 'qux'].includes(key))
);
可重用的功能
一行程序可以表示为类似于Lodash pick或省略的可重用帮助函数,其中通过参数pick(obj, 'foo-bar', 'bar', 'baz')传递键列表。
const pick = (obj, ...keys) => Object.fromEntries(
keys
.filter(key => key in obj)
.map(key => [key, obj[key]])
);
const inclusivePick = (obj, ...keys) => Object.fromEntries(
keys.map(key => [key, obj[key]])
);
const omit = (obj, ...keys) => Object.fromEntries(
Object.entries(obj)
.filter(([key]) => !keys.includes(key))
);
动态属性的解构赋值
这个解决方案不仅适用于你的具体例子,而且更普遍适用:
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等,以考虑更多的属性。