如何在Array.prototype.reduce()函数中处理eslint no-param-reassign规则

sfl*_*che 25 javascript ecmascript-6 eslint

我最近添加了eslint规则no-param-reassign.

但是,当我reduce用来构建一个对象(空对象initialValue)时,我发现自己需要accumulator在每次回调迭代时修改(回调函数的第一个arg),这会引起一个no-param-reassignlinter投诉(正如人们所期望的那样).

const newObject = ['a', 'b', 'c'].reduce((result, item, index) => {
  result[item] = index; // <-- causes the no-param-reassign complaint
  return result;
}, {});
Run Code Online (Sandbox Code Playgroud)

是否有更好的方法来构建一个reduce不修改accumulator参数的对象?

或者我应该简单地在reduce回调函数中禁用该行的linting规则?

Anj*_*Anj 33

每当我使用时,Array.prototype.reduce我总是命名“accumulator”参数accu。这个约定让我可以方便地设置我的 eslint 规则:

    "no-param-reassign": [
      "error",
      {
        "props": true,
        "ignorePropertyModificationsFor": ["accu"]
      }
    ],
Run Code Online (Sandbox Code Playgroud)

如果您对此参数有自己的命名约定,请将上面规则中的“accu”替换为您使用的任何内容,并且 eslint 不会抱怨修改您的累加器。

  • 在我遇到的每种情况下,输出将分配到的变量名称(以及函数中发生的情况)都有足够的上下文,这不是问题。如果函数过于复杂(但情况并非如此),则重构并采取不同的方法可能是有意义的。 (3认同)
  • 我同意@Anj,上面的观点在这方面是迂腐的。 (2认同)

Zac*_*opp 19

我只是将 reduce 函数包装在一个 lint 规则禁用块中,即:

/* eslint-disable no-param-reassign */
const newObject = ['a', 'b', 'c'].reduce((result, item, index) => {
  result[item] = index;
  return result;
}, {});
/* eslint-enable no-param-reassign */
Run Code Online (Sandbox Code Playgroud)

  • 出于性能原因,这应该是正确的答案。我相信这是最优的解决方案。No-param-reassign 是一种防止我们在范围之外产生副作用的方法,但 Array.reduce 的情况是副作用问题的一个例外,因为它内部是纯粹的。 (5认同)

sfl*_*che 17

我正在重新审视这个问题,以便使用对象扩展运算符发布最终发生的新答案)...

const newObject = ['a', 'b', 'c'].reduce((result, item, index) => ({
  ...result,
  [item]: index, 
}), {});
Run Code Online (Sandbox Code Playgroud)

  • 这真是一个很好的解决方案吗?减少具有许多元素的数组,比如2000,将创建尽可能多的新对象实例,例如2000. (10认同)
  • 正如其他人之前所说,这不是高性能的。您应该禁用该行中的 lint 规则。也许可以要求 eslint 人员考虑专门为 Array.reduce 添加一个异常 (3认同)

Ber*_*rgi 9

好吧,你可以(result, item) => Object.assign({}, result, {[item]: whatever})在每次迭代时创建一个新对象:-)

如果你想欺骗linter,你可以使用=> Object.assign(result, {[item]: whatever})(它与你当前的代码相同但没有明确的赋值),但是我想你应该简单地禁用该规则.

  • 是的,这有点像我想的那样.也许禁用该行的规则是最好的选择...... (2认同)