Skip to content

根据键或值过滤JavaScript对象的属性

JavaScript为数组提供了非常丰富的API,但对于对象来说却不是这样。这是可以理解的,因为可以应用于对象的方法不能与对象的属性冲突。

尽管如此,作为Object API的一部分提供的内容非常有限,因此如果我们想要进行更复杂的操作,就必须在其基础上进行构建。其中一个用例就是根据键数组或谓词函数来过滤对象的属性

根据键过滤对象属性

给定一个对象,我们想要根据一个键数组来过滤其属性。结果应该是一个新对象,其中只包含键包含在数组中的属性。

为了实现这一点,我们将利用Object.entries()来获取对象的键值对数组,然后使用Array.prototype.filter()根据提供的数组来过滤键值对。最后,使用Object.fromEntries()我们可以将过滤后的键值对转换回对象。

我们还可以实现反向操作,即过滤掉键包含在数组中的属性。只需在Array.prototype.filter()回调中否定条件即可。

const pick = (obj, arr) =>
  Object.fromEntries(Object.entries(obj).filter(([k]) => arr.includes(k)));

const omit = (obj, arr) =>
  Object.fromEntries(Object.entries(obj).filter(([k]) => !arr.includes(k)));

const obj = { a: 1, b: '2', c: 3 };

## 根据键值选择对象属性

如果我们想根据给定的键数组选择对象的属性,可以使用`pick`函数。例如,我们可以选择对象`obj`中的键为`'a'`和`'c'`的属性。

```js
const pick = (obj, keys) =>
  keys.reduce((acc, key) => {
    if (obj.hasOwnProperty(key)) {
      acc[key] = obj[key];
    }
    return acc;
  }, {});

const omit = (obj, keys) =>
  Object.keys(obj).reduce((acc, key) => {
    if (!keys.includes(key)) {
      acc[key] = obj[key];
    }
    return acc;
  }, {});

const obj = { a: 1, b: '2', c: 3 };

pick(obj, ['a', 'c']); // { 'a': 1, 'c': 3 }
omit(obj, ['b']); // { 'a': 1, 'c': 3 }

有条件地过滤对象属性

前面的代码片段涵盖了大多数简单的用例,但是如果我们想根据一个谓词函数来过滤对象的属性呢?例如,我们可能想过滤掉所有值为数字的属性。

这也不是特别难实现。我们只需将数组包含检查替换为对提供的谓词函数的调用。为了使我们的函数的API更加用户友好,谓词函数应该将值作为第一个参数,将键作为第二个参数。

const pickBy = (obj, fn) =>
  Object.fromEntries(Object.entries(obj).filter(([k, v]) => fn(v, k)));

const omitBy = (obj, fn) =>
  Object.fromEntries(Object.entries(obj).filter(([k, v]) => !fn(v, k)));

const obj = { a: 1, b: '2', c: 3 };

pickBy(obj, x => typeof x === 'number'); // { a: 1, c: 3 }
omitBy(obj, x => typeof x !== 'number'); // { a: 1, c: 3 }