如何获取 javascript 对象属性的子集

新手上路,请多包涵

假设我有一个对象:

elmo = {
  color: 'red',
  annoying: true,
  height: 'unknown',
  meta: { one: '1', two: '2'}
};

我想用其属性的子集制作一个新对象。

 // pseudo code
 subset = elmo.slice('color', 'height')

 //=> { color: 'red', height: 'unknown' }

我怎样才能做到这一点?

原文由 Christian Schlensker 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.4k
2 个回答

使用对象解构和属性简写

 const object = { a: 5, b: 6, c: 7 };
 const picked = (({ a, c }) => ({ a, c }))(object);

 console.log(picked); // { a: 5, c: 7 }

来自菲利普·凯维施:

这实际上只是一个被立即调用的匿名函数。所有这些都可以在 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)

原文由 Ivan Nosov 发布,翻译遵循 CC BY-SA 4.0 许可协议

两种常见的方法是 解构 和传统的类 pick / omit 实现。它们之间的主要实际区别是,解构要求键列表是静态的,不能省略它们,包括不存在的选择键,即它是包容性的。这可能是合意的,也可能不是合意的,并且不能针对解构语法进行更改。

鉴于:

 var obj = { 'foo-bar': 1, bar: 2, qux: 3 };

定期挑选 foo-barbarbaz 键的预期结果:

 { 'foo-bar': 1, bar: 2 }

包容性 拣选的预期结果:

 { 'foo-bar': 1, bar: 2, baz: undefined }

解构

解构语法允许使用函数参数或变量来解构和重组对象。

限制是键列表是预定义的,它们不能列为字符串,如问题中所述。如果密钥是非字母数字,则解构会变得更加复杂,例如 foo-bar

好处是它是 ES6 天生的高性能解决方案。

缺点是键列表是重复的,如果列表很长,这会导致代码冗长。由于在这种情况下解构会复制对象字面量语法,因此可以按原样复制和粘贴列表。

经济研究所

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.entriesArray.prototype.includes ,ECMAScript 2019 有 Object.fromEntries

单线

考虑到要选择的对象包含额外的键,迭代列表中的键而不是对象键通常更有效,如果需要省略键,反之亦然。

选择 (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 pickomit 的可重用辅助函数,其中键列表通过参数传递, 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))
);

原文由 Estus Flask 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题