【问题标题】:What is the most elegant way to remove an array of properties from an object immutably in JavaScript?在 JavaScript 中从对象中不可变地删除一组属性的最优雅的方法是什么?
【发布时间】:2020-07-27 19:44:37
【问题描述】:

不确定我是否想以一种优雅的方式在这里完成太多事情,但假设我有一个对象如下:

const obj = { foo: 'bar', prop: 'str', hi: 'hello' };

然后我有一个要从该对象中删除的属性数组:

const keys = ['prop', 'hi'];

我正在寻找能够不变地获得以下输出的最佳方式:

{ foo: 'bar' }

我正在研究使用解构赋值,但我不知道如何使它与属性数组一起工作,除非它具有静态长度:

({ [keys[0]]: value, [keys[1]]: value, ...output }) = o;

也许有另一种方法来执行上述行但使用映射?

谢谢!

【问题讨论】:

  • “不可变”是指要创建一个具有相同键的新对象,但省略keys 中命名的键吗?
  • 定义“优雅”
  • 他没有要求“一个优雅的解决方案”“我一看到就知道”有点适用)。他要了“最优雅的”。可量化,它需要定义。
  • 哪个最优雅?我想当我看到它时我会知道的。 :-)。不过,更严重的是,在Simple Made Easy 中,Rich Hickey 描述了对代码简单性的合理客观定义。在我看来,简约和优雅是相辅相成的。

标签: javascript arrays object ecmascript-6 immutability


【解决方案1】:

您可以迭代数组并使用 delete 删除每个匹配的键。

要复制您拥有的对象,您可以使用扩展运算符

const keys = ['prop', 'hi'];
const obj = { foo: 'bar', prop: 'str', hi: 'hello' };
const newobj={...obj}
keys.forEach(o=> delete newobj[o])
console.log(obj)
console.log(newobj)
这是使用Object.fromEntriesfiltersome 的另一种方法

const keys = ['prop', 'hi'];
const obj = { foo: 'bar', prop: 'str', hi: 'hello' };
res=Object.fromEntries(Object.entries(obj).filter(o=>!keys.some(k=>o[0]==k)))
console.log(res)
console.log(obj)

【讨论】:

  • 这会使obj 发生变异,这似乎不符合 OP 的要求。
  • @Code-Apprentice 感谢您指出这一点,现已修复
  • 你的第一个很好,因为它不会运行缓慢的 [].includes() 并且可读性很高。
  • @dandavis 谢谢,虽然如果对象太复杂而无法使用扩展运算符克隆,建议使用第二种方法
  • 我必须进行基准测试才能知道哪个更好,除非它是我的代码中可证明的热点,否则我什至不会打扰
【解决方案2】:

我会结合使用Object.fromEntriesObject.entries 和数组.filter 方法。那么这个操作就变得非常简单了:

function removeKeysFromObj(obj, keys) {
  return Object.fromEntries(Object.entries(obj).filter(([key]) => !keys.includes(key)));
}

const obj = { foo: 'bar', prop: 'str', hi: 'hello' };
const keys = ['prop', 'hi'];

const newObj = removeKeysFromObj(obj, keys);

console.log("New object:", newObj);

// And note the original is unmodified:
console.log("Original object:", obj);

【讨论】:

    【解决方案3】:

    解决这个问题的一种方法是反过来思考:映射原始对象中的键并保留不在列表中的键:

    function removeKeys(obj, keys) {
        return Object.keys(obj)
            .filter(k => !keys.includes(k))
            .reduce((newObj, k) => {
                newObj[k] = obj[k];
                return newObj
            }, {});
    

    【讨论】:

    • obj.keys() 是指Object.keys(obj)
    【解决方案4】:

    我会这样做。

    const obj = { foo: 'bar', prop: 'str', hi: 'hello' };
    const keys = ['prop', 'hi'];
    let result = Object.keys(obj).reduce((current, item) => (keys.includes(item) || (current[item] = obj[item]), current), {});
    console.log(result);

    【讨论】:

      猜你喜欢
      • 2020-12-30
      • 2012-12-29
      • 2010-09-27
      • 2016-03-27
      • 1970-01-01
      • 2015-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多