【问题标题】:Changing the reference of a js function's argument更改 js 函数参数的引用
【发布时间】:2019-04-21 19:10:27
【问题描述】:

最近我编写了 react-redux 应用程序,作为一名 React 开发人员,我编写了纯正、实用且可预测的代码。尽管我确实喜欢这种体验,但我怀疑我的代码是否仍然漂亮。

所以我的状态中有一棵树,我需要更新树中的一堆节点。假设树的 API 提供了一个 pure 方法pureUpdate(path, newNode, tree) => newTree,它返回更新了节点的新树。在这种情况下,我的减速器方法可能看起来像

function updateNodes(tree, updateRules) {
    updateRules.forEach(updateRule => {
        const { path, node } = updateRule;
        tree = pureUpdate(path, node, tree);
    });
    return tree;
}

但我不确定这是否是最好的。

首先看起来很讨厌的是tree = pureUpdate(path, node, tree);。它看起来像改变一个参数,这是不鼓励的,但我只是重新分配 参考,不是吗?在答案的第二部分中解释了here。但是尽管这个技巧可能没问题,in this discussion 表示此类代码可能未优化并且重新分配参数可能会导致性能问题 (more info with examples)。我想到的最简单的解决方法是使用一个额外的变量,它将是树的克隆。

function updateNodes(tree, updateRules) {
    let newTree = someCloneFunc(tree);
    updateRules.forEach(updateRule => {
        const { path, node } = updateRule;
        newTree = pureUpdate(path, node, newTree);
    });
    return newTree;
}

问题是,如果我没有遗漏任何东西,并且我的代码仍然是纯粹的、漂亮的并且不会引起任何问题。

【问题讨论】:

  • 如果你想做纯粹的函数式编程,永远不要使用forEach

标签: javascript redux functional-programming


【解决方案1】:

如果您完全关心性能,我不会克隆 tree 只是为了避免重新分配参数。

虽然您可以在此处使用forEach 并重新分配参数,但reduce 是您的用例的正确功能抽象,它通常比forEach 更好、更有用,因为它可以(并且应该)是纯粹使用,而forEach 总是关于副作用。

基于reduce 的解决方案也使得是否克隆和/或重新分配函数参数的问题完全没有意义。

这是一个有效的 reduce 解决方案 - 没有参数重新分配,没有 forEach 副作用,也没有理由克隆 tree

const updateNodes = (tree, updateRules) =>
  updateRules.reduce(
    (acc, { path, node }) => pureUpdate(path, node, acc),
    tree // initialize acc (the accumulator)
  )

【讨论】:

    猜你喜欢
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 2014-03-15
    • 2018-12-30
    • 1970-01-01
    相关资源
    最近更新 更多