首页 > 解决方案 > 在地图对象中设置和删除时确保原始文件的不变性

问题描述

我一直在研究如何在 JavaScript 中完成不变性/函数式编程,但我在使用以下代码时遇到了困难。从generateExample函数返回的对象包含通过迭代对象数组来从映射中添加和删除键/值的方法。

场景 1 简单地使用 map 方法setdelete方法,并对 map 进行变异。setting场景 2 在和deleting键/值之前创建一个新映射。

set我可以在每个循环中为每个 new 克隆地图foreach,但我想这在计算上会太昂贵。

我还可以使用 Immutable.js (Map) 并为每个set和返回一个新的数据结构delete。我真的不想这样做。

从这个例子中返回的对象generateExample将是唯一可以setdelete映射到地图的对象,所以也许担心这个例子中的不变性并不重要?

我想了解的是在设置和删除键/值时保持原始地图不变性的最佳方法是什么,甚至是否相关?

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'))

标签: javascript

解决方案


在这两种情况下,您都有突变。在第一种情况下,突变在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)
    },
  }
}

推荐阅读