【问题标题】:Javascript: normalize argument in a function, should I copy it?Javascript:规范化函数中的参数,我应该复制它吗?
【发布时间】:2018-09-25 19:50:18
【问题描述】:

假设有一个函数:

const foo = (arg) => { do_something };

在我运行do_something 之前,我实际上想将arg 标准化为一个数组,因为该函数接受字符串或数组以外的类型。

我知道直接修改函数中传递的参数是一种不好的做法,因为它可能会发生变异并导致难以调试的错误。所以,我会做这样的事情:

const foo = (arg) => {
  const _arg = Array.isArray(arg) ? [...arg] : [arg];
  do_something(_arg)
};

如上所述,我实际上对该数组做了一个浅拷贝(arg),然后使用_arg 做一些事情,并且我会确保不会对其进行变异(因为它只是一个浅拷贝)。我的问题是,如果我不复制它怎么办?即:

const foo = (arg) => {
  const _arg = Array.isArray(arg) ? arg : [arg];
  do_something(_arg)
};

会有所不同吗?或者哪一种是更好/更健康的编码方式?它会影响垃圾收集或任何性能问题吗?

感谢您的回答。

【问题讨论】:

  • 经验法则:无突变 = 无需复制。但是,您的do_something 非常有限。它只知道_arg[?] 的数组。因此它只能执行不需要知道任何元素类型的数组操作,例如sliceconcat 等。
  • 是的,我现在只想做数组选项,我可能会在do_something 中做_array.filter(ele => typeof ele === ‘function’),以确保我只有一个函数集合。

标签: javascript functional-programming normalization


【解决方案1】:

IMO,建议使用第一种方法,因为如果do_something 引起一些副作用,第二种方法通常会导致意外问题。

会影响垃圾回收吗?是的。使用第一种方法,_arg 将被清除,因为没有任何引用它。我不确定性能。这取决于您处理的数据大小。

【讨论】:

  • 感谢您的回答: 1. 它说我应该做一个深度克隆?!因为浅拷贝并不能保证任何东西...... 2.只是想澄清一下,如果我在函数中不返回_arg,那么它就变成了垃圾回收权(没有引用的意思)?!抱歉,我还没有完全理解 JS 垃圾收集...
  • 1.是的,至少在特定情况下。否则很难回答。有时我们不需要使程序更复杂。 2. 是的。 JS GC 使用“Reference-counting”和“Mark-and-sweep”算法。你可以在这里阅读更多:developer.mozilla.org/en-US/docs/Web/JavaScript/…
【解决方案2】:

我担心你的两分钱是,在默认情况下没有不变性的语言中,我会坚持编码约定而不是试图模仿不变性。

也就是说,如果你声明数组不能被修改,并且如果一个新元素应该被推送或者替换你需要使用Array.prototype.concat或者数组扩展操作符,我相信你的代码会更简单,更容易遵循和维护。

此外,您可能希望使用不可变集合,例如 ImmutableJS 提供的集合。

【讨论】:

  • 是的,我相信是这样,但有时很难做到。特别是当我在 Node/Express 上工作时。我必须改变 res 对象以保持中间件正常工作。所以很难坚持数组的不变偏好有时会使编码变得困难?!但是,从您的回答中,我知道我应该建立一种一致的方式来处理我的代码!我想我会遵循之前 cmets 中提到的经验法则,并尽可能让代码不那么复杂。
  • @LeoLi 所以,归根结底,您可以将纯 FP 与可变性混合使用。我正在努力解决来自 Express 的 Response 对象的相同问题,但我已经习惯了不要尝试改变数组、对象......现在我们已经有了数组和对象属性扩展运算符,更容易理解规则并产生优雅的代码!
猜你喜欢
  • 2020-05-08
  • 2011-08-26
  • 2016-11-12
  • 2018-07-08
  • 2013-07-26
  • 2011-07-17
  • 1970-01-01
  • 2010-12-09
  • 2011-02-06
相关资源
最近更新 更多