【问题标题】:How do immutable methods work in lodash fp?不可变方法如何在 lodash fp 中工作?
【发布时间】:2021-03-11 08:00:10
【问题描述】:

我想了解 lodash/fp 的不可变方法是如何工作的。

他们是在更改之前对集合进行深度克隆,还是在对象的两个版本之间实现某种结构共享?

我试图“从外部”理解它,但我无法得出明确的结论。

在下面的第一种情况下,改变更新的集合不会影响原始集合。

但是,在第二种情况下,对更新的集合进行变异确实会影响原始集合。

var fp = _.noConflict();

var data = { a: { c: {} } };
var updatedData = fp.set(["a", "c", "d"], 5, data);
updatedData.a.c.e = 9;
console.log(updatedData.a.c.e, data.a.c.e);

var data2 = { a: { c: [] } };
var updatedData2 = fp.set(["a", "d"], 5, data2);
updatedData2.a.c[0] = 9;
console.log(updatedData2.a.c[0], data2.a.c[0]);
<script src='https://cdn.jsdelivr.net/g/lodash@4.17(lodash.min.js+lodash.fp.min.js)'></script>

我也在Lodash github上发布了这个问题。

【问题讨论】:

  • 你能告诉我是什么让我的 sn-p 不是最小的吗?
  • 哦,对不起,看错问题了...
  • 如果我对the source 的理解正确,Lodash 会克隆被调用函数的所有参数,因此您的第一个示例几乎不等于_.set(["a", "c", "d"], 5, _.cloneDeep(data))
  • 如果有 cloneDeeep,那么在第二个例子中 data.a.c[0] 应该是 9
  • 我不知道 lodash 但是树(由对象形成)可以通过将路径从根复制到更新的叶子来共享结构,从而有效地获得不变性。您不能对数组执行此操作。造成这种差异的更深层原因是树是递归的,因此是代数数据结构,而数组不是。

标签: javascript functional-programming lodash immutability


【解决方案1】:

他们是在更改之前对集合进行深度克隆,还是在对象的两个版本之间实现某种结构共享?

是的,他们使用结构共享。

我们可以在这个例子中看到c 对象被重用,而不是被克隆。这很有用,因为它的大小可能非常大(在我的例子中,它包含整个 window 对象!)。
你可以想象尝试深度克隆它会浪费资源。

var fp = _.noConflict()
var data, updatedData


data = { a: { c: { window: window } } }
updatedData = fp.set(["a", "d"], 5, data)
console.log(updatedData.a.c === data.a.c)
<script src='https://cdn.jsdelivr.net/g/lodash@4.17(lodash.min.js+lodash.fp.min.js)'></script>

只有“父”对象被更改,所以它们必须被克隆。不属于突变的叶子不需要改变。

在您的示例中出现问题的原因是您将不可变代码和可变代码组合在一起,这不是一个好主意。如果您对预期不可变的代码进行变异,这些克隆优化显然会出错。

【讨论】:

    猜你喜欢
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-31
    • 1970-01-01
    • 2020-10-20
    相关资源
    最近更新 更多