Javascript 在设置贴图对象并从中删除时确保原始对象的不变性

Javascript 在设置贴图对象并从中删除时确保原始对象的不变性,javascript,Javascript,我一直在研究如何在JavaScript中实现不变性/函数式编程,我对下面的代码有困难。从generateExample函数返回的对象包含通过迭代对象数组从映射中添加和删除键/值的方法 场景1仅使用map方法set和delete方法并对map进行变异。场景2在设置和删除键/值之前创建一个新映射 我可以在每个foreach循环中为每个新的集合克隆映射,但我认为这在计算上太昂贵了 我还可以使用Immutable.js(Map),并为每个集合和删除返回一个新的数据结构。我真的不想这么做 在本例中,从ge

我一直在研究如何在JavaScript中实现不变性/函数式编程,我对下面的代码有困难。从
generateExample
函数返回的对象包含通过迭代对象数组从映射中添加和删除键/值的方法

场景1仅使用map方法
set
delete
方法并对map进行变异。场景2在
设置
删除
键/值之前创建一个新映射

我可以在每个
foreach
循环中为每个新的
集合
克隆映射,但我认为这在计算上太昂贵了

我还可以使用Immutable.js(Map),并为每个
集合
删除
返回一个新的数据结构。我真的不想这么做

在本例中,从
generateeexample
返回的对象将是唯一可以
set
delete
到映射的对象,因此在本例中担心不可变性可能并不重要

我想了解的是,在设置和删除键/值时,保持原始映射的不变性的最佳方法是什么,以及它是否相关

const sampleList = [
  {
    id: 'dog',
    value: 'Dog',
  },
  {
    id: 'cat',
    value: 'Cat',
  },
]
情景1

const example = function generateExample() {
  const container = new Map()
  return {
    add(list) {
      list
        .forEach((x) => {
          container.set(x.id, x)
        })
    },
    remove(list) {
      list
        .forEach((x) => {
          container.delete(x.id)
        })
    },
    read(id) {
      return container.get(id)
    },
  }
}
场景2

const example = function generateExample() {
  let container = new Map()
  return {
    add(list) {
      container = new Map(container)
      list
        .forEach((x) => {
          container.set(x.id, x)
        })
    },
    remove(list) {
      container = new Map(container)
      list
        .forEach((x) => {
          container.delete(x.id)
        })
    },
    read(id) {
      return container.get(id)
    },
  }
}

const test = example()
test.add(sampleList)
console.log(test.read('dog'))

在这两种情况下,你都有突变。在第一个场景中,变异发生在
Map
对象上,在第二个场景中,变异发生在容器值本身上,然后再次发生在
Map
对象上。我建议不要使用此层,只需按原样处理
Map
对象,但如果情况必须是这样,我更愿意这样做

const example = function generateExample(defaultList) {
  let container = new Map(defaultList)
  return {
    add(list) {
      container = new Map(container.concat(list));
    },
    remove(list) {
      container = new Map(container.filter(item => !list.includes(item)))
    },
    read(id) {
      return container.get(id)
    },
  }
}