使用 Lodash 或 Underscore 检查对象是否只有给定的键

Check if object has only the given keys using Lodash or Underscore

是否有 Lodash 或 Underscore 方法可以查找对象是否仅具有该对象的给定键。我想要一个 Lodash 或 Underscore 实现,尽管使用原生 JS 这听起来微不足道。

例如,如果我的对象看起来像并假设有一个名为 hasOnly

的 lodash 方法
const obj = {
    name: undefined,
  age: 15,
  school: 'Some school'
}

_.hasOnly(obj,['name','age']) //return false

_.hasOnly(obj,['name','age','city']) //return false

_.hasOnly(obj,['name','age','school']) //return true

我似乎无法在文档中找到方法

快速而肮脏:

hasOnly = (obj, props) => _.isEqual(_.keys(obj).sort(), props.sort())

排序完成,因为我们正在比较数组。

作为替代方案,可以将 props_.keys(obj) 都变成对象,其中 props_.keys(obj) 是键,而值是虚拟键, 始终相同,例如 1。这样做的功能可能是这样的:

make1ValuedObj = keys => _.zipObject(keys, Array(keys.length).fill(1))

然后将它们传递给 _.isEqual 而无需对任何内容进行排序:

hasOnly = (obj, props) => _.isEqual(make1ValuedObj(_.keys(obj)), make1ValuedObj(props))

实际情况是,当您构造对象时必须进行某种“排序”,所以我认为与上述解决方案相比并没有真正的优势。

在几乎所有情况下,本机解决方案都会更快:

const obj = {
  name: undefined,
  age: 15,
  school: 'Some school'
}

const hasOnly = (obj,props) => {
    var objProps = Object.keys(obj)
    return objProps.length == props.length && props.every(p => objProps.includes(p))
}

console.log(hasOnly(obj,['name','age'])) //return false

console.log(hasOnly(obj,['name','age','city'])) //return false

console.log(hasOnly(obj,['name','age','school'])) //return true

将此与使用 lodash 的其他答案进行基准测试表明 lodash 解决方案要慢 95%(在我的机器上)

基准:https://jsbench.me/r9kz2mwr9c/1

我认为 Enlico 的回答很好,但为了完整起见,我会提到另一个不需要排序的选项。这是基于直接比较对象而不是比较键数组。

请注意,下面的代码采用原始下划线。对于 Lodash,将 _.mapObject 替换为 _.mapValues

// replace all properties by true to prevent costly recursion
const mask = obj => _.mapObject(obj, _.constant(true));

function hasOnly(obj, keys) {
    const masked = mask(obj);
    // compare obj to a trimmed version of itself
    return _.isEqual(masked, _.pick(masked, keys));
}