如何从 arr.map(elem => dict[elem]) 中提取函数?
一个函数应该只做一件事被认为是编写函数时的一个好习惯。然而,我有一个已经非常小的函数,但尽管如此,我认为可以进一步提取它,但我不知道如何做到这一点。
以下 recode()
函数根据查找字典替换数组值。
function recode(arr, dict) {
return arr.map(elem => dict[elem])
}
它如何工作的示例:
// input data to be recoded
const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage'];
// look-up dictionary
const myDict = {
eggplant: 'purple',
tomato: 'red',
carrot: 'orange',
};
const result1 = recode(myArr, myDict)
console.log(result1) // => ["purple", "red", "orange", undefined]
在我看来,当前的 recode()
函数做了两件事:
- 它按身份匹配(您可能有比这更好的描述),即
elem =>字典[元素]
;它 - 映射到 arr
我的问题是我是否可以为 elem => 提取单个函数dict[elem],并将该函数提供给 arr.map()
。我想象一下:
// pseudo-code
function funcInner() {...}
function recode(arr, dict) {
return arr.map(funcInner)
}
这样,我将拥有一个仅执行替换的函数,另一个仅映射 arr
。
编辑
为了解决这些评论,我想打个比方。让我们考虑一个将数组值加倍的函数。
function doubleArray(arr) {
return arr.map(x => x * 2)
}
这里有些人可能会说 doubleArray() 已经在做一件事了。但是,我们仍然可以提取:
const doubleNumber = x => x * 2;
function doubleArray2(arr) {
return arr.map(doubleNumber)
}
据我了解,doubleArray() 做了两件事(double 和 map),而 doubleArray2()
只做了一件事(map ) 和 doubleNumber() 只做一件事(双精度)。因此,doubleArray()
并不是无意义的重构。
此外,一旦我们有了一个可以做一件事的函数,它就会促进我们可以为其编写更准确的单元测试。
最后,如果我们将此代码转换为 typescript (我在这个问题中没有重点关注),那么 doubleNumber()
中的输入类型与输入类型不同在 doubleArray() 中。这就是我更愿意提取的另一个原因。
我对 javascript 很陌生,但这就是我理解它的方式。所以我关于 recode()
的问题就是在这种情况下发生的。
A function should do only one thing is considered a good practice when writing functions. However, I have a function that is already very minimal, but nevertheless I think it can be further extracted, but I don't know how this can be done.
The following recode()
function replaces array values according to a look-up dictionary.
function recode(arr, dict) {
return arr.map(elem => dict[elem])
}
Example to how it works:
// input data to be recoded
const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage'];
// look-up dictionary
const myDict = {
eggplant: 'purple',
tomato: 'red',
carrot: 'orange',
};
const result1 = recode(myArr, myDict)
console.log(result1) // => ["purple", "red", "orange", undefined]
The way I see it, the current recode()
function does two things:
- It matches by identity (you might have a better description than this), i.e.,
elem => dict[elem]
; and - it maps over
arr
My question is whether I can extract an individual function for elem => dict[elem]
, and supply that function to arr.map()
. I imagine something along the lines of:
// pseudo-code
function funcInner() {...}
function recode(arr, dict) {
return arr.map(funcInner)
}
This way, I will have one function that does only the replacement, and another that only maps over arr
.
EDIT
To address the comments, I would like to make an analogy. Let's consider a function that doubles array values.
function doubleArray(arr) {
return arr.map(x => x * 2)
}
Some folks here might say that doubleArray()
is already doing one thing. However, we could still extract:
const doubleNumber = x => x * 2;
function doubleArray2(arr) {
return arr.map(doubleNumber)
}
As far as I understand, doubleArray()
did two things (double & map), whereas doubleArray2()
does only one thing (map) and doubleNumber()
does one thing (doubles). Therefore, doubleArray()
is not a meaningless refactoring.
Furthermore, once we have a function that does one thing, it promotes more accurate unit tests we can write for it.
Lastly, if we translated this code to typescript (which I didn't focus on in this question), then the input type in doubleNumber()
is different than the input type in doubleArray()
. So that's another reason why I would prefer to extract.
I'm very new to javascript, but this is the way I understand it. So my question about recode()
was within this context.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
回答你的问题:
但我同意其他人对你的问题的评论,这可能有点矫枉过正。你的选择。
To answer your question:
But i agree with the others commenting on you question, this may be a little overkill. Your choice.
本质上,
recode
被用作arr.map()
。这也可以通过将recode
分配给调用Function.bind()
方法。myArr
需要作为第一个参数传递以绑定数组的上下文。但也许直接调用
.map()
更简单:如果需要用户提供的回调,则 可以使用 ES-6 默认参数:
In essence
recode
is being used a wrapper aroundarr.map()
. This could also be achieved by assigningrecode
to a function returned by calling theFunction.bind()
method.myArr
needs to be passed as the first parameter to bind the context of the array.But perhaps it is simpler just to call
.map()
directly:If there is a desire to have a user-supplied callback, then the ES-6 default parameters could be used:
Daniel 的回答略有不同:让另一个函数返回一个可用作 Array# 回调的函数map:
但我也会质疑这是否真的是对原始代码的改进。
A slight variation on Daniel's answer: Have the other function return a function that can be used as callback for
Array#map
:But I would also question whether this is really an improvement over your original code.
您不需要在您的情况下进行提取,这就是箭头函数存在的原因。
You do not need to extract in your case, thats why arrow functions exist.