在撰寫函式時,一個函式應該只做一件事被認為是一種好的做法。但是,我有一個功能已經非常小,但是我認為可以進一步提取它,但我不知道如何做到這一點。
以下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 => dict[elem];和 - 它映射了
arr
我的問題是我是否可以為 提取單個函式elem => dict[elem],并將該函式提供給arr.map(). 我想像這樣的事情:
// 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.
uj5u.com熱心網友回復:
要回答您的問題:
function recode(arr, dict) {
return arr.map(elem => funcInner(elem,dict));
};
function funcInner(elem, dict) {
return dict[elem];
}
但我同意其他人對你的問題的評論,這可能有點矯枉過正。你的選擇。
uj5u.com熱心網友回復:
本質上recode是在使用一個包裝器arr.map()。這也可以通過分配給呼叫方法recode回傳的函式來實作。Function.bind()
const recode = myArr.map.bind(myArr, elem => myDict[elem]);
myArr需要作為第一個引數傳遞來系結陣列的背景關系。
// input data to be recoded
const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage'];
// look-up dictionary
const myDict = {
eggplant: 'purple',
tomato: 'red',
carrot: 'orange',
};
const recode = myArr.map.bind(myArr, elem => myDict[elem]);
const result1 = recode(myArr, myDict)
console.log(result1) // => ["purple", "red", "orange", undefined]
但也許.map()直接呼叫更簡單:
// input data to be recoded
const myArr = ['eggplant', 'tomato', 'carrot', 'cabbage'];
// look-up dictionary
const myDict = {
eggplant: 'purple',
tomato: 'red',
carrot: 'orange',
};
const result1 = myArr.map(elem => myDict[elem])
console.log(result1) // => ["purple", "red", "orange", undefined]
如果希望有一個用戶提供的回呼,那么可以使用ES-6 默認引數:
function recode(myArr, myDict, callback = elem => myDict[elem]) {
return myArr.map(callback);
}
// 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]
const result2 = recode(myArr, myDict, elem => myDict[elem] 'a')
console.log(result2) // => ["purplea", "reda", "orangea", "undefineda"]
uj5u.com熱心網友回復:
丹尼爾的回答略有不同:讓另一個函式回傳一個可以用作回呼的函式Array#map:
function createMapper(dict) {
return elem => dict[elem];
}
function recode(arr, dict) {
return arr.map(createMapper(dict));
}
但我也會質疑這是否真的是對您原始代碼的改進。
uj5u.com熱心網友回復:
您不需要提取您的情況,這就是存在箭頭功能的原因。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/438548.html
標籤:javascript function dictionary ecmascript-6 functional-programming
下一篇:按索引更改值字典
