在 Javascript 中,函數就是值(一等公民)。這意味著它們可以分配給變數和/或作為值傳遞。
let random = function(){
return Math.random()
}
let giveMeRandom = random // assigning random to a variable
這項知識使我們能夠用這種語言編寫函數式程式設計。在函數式程式設計中,我們大量使用高階函數。
高階函數是將其他函數作為參數或返回函數作為結果的函數。
以其他函數作為參數通常稱為“回調函數”,因為它是由高階函數回調的。這是 Javascript 常用的概念。
例如,陣列上的 map 函數是一個高階函數。 map 函數接受一個函數作為參數。
const double = n => n * 2
[1, 2, 3, 4].map(double) // [ 2, 4, 6, 8 ]
或者,使用匿名函數:
[1, 2, 3, 4].map(function(n){
return n * 2
}) // [ 2, 4, 6, 8 ]
map 函數是該語言內建的眾多高階函數之一。 sort、reduce、filter、forEach 是該語言內建的高階函數的其他範例。
高階函數可讓您編寫更簡單、更優雅的程式碼。讓我們看看如果沒有這樣的抽象,上面的程式碼會是什麼樣子。讓我們用循環取代 map 函數:
let array = [1, 2, 3, 4]
let newArray = []
for(let i = 0; n < array.length; i++) {
newArray[i] = array[i] * 2
}
newArray // [ 2, 4, 6, 8 ]
盡可能使用高階函數的一大優點是組合。
我們可以建立更小的函數,只處理一個邏輯。然後,我們透過使用不同的較小函數來組合更複雜的函數。
這種技術減少了錯誤並使我們的程式碼更易於閱讀和理解。
透過學習使用高階函數,您可以開始編寫更好的程式碼。
讓我們試著舉個例子。假設我們有一個教室的成績清單。我們的教室有 5 個女孩,5 個男孩,每個人的成績都在 0 到 20 之間。
var grades = [
{name: 'John', grade: 8, sex: 'M'},
{name: 'Sarah', grade: 12, sex: 'F'},
{name: 'Bob', grade: 16, sex: 'M'},
{name: 'Johnny', grade: 2, sex: 'M'},
{name: 'Ethan', grade: 4, sex: 'M'},
{name: 'Paula', grade: 18, sex: 'F'},
{name: 'Donald', grade: 5, sex: 'M'},
{name: 'Jennifer', grade: 13, sex: 'F'},
{name: 'Courtney', grade: 15, sex: 'F'},
{name: 'Jane', grade: 9, sex: 'F'}
]
我想了解一些關於此事的事情:
該班的平均成績
男生的平均成績
女孩的平均成績
男孩中音調較高的
女孩中的最高調
我們將嘗試使用高階函數來獲得簡單易讀的程式。讓我們從編寫可以協同工作的簡單函數開始:
let isBoy = student => student.sex === 'M'
let isGirl = student => student.sex === 'F'
let getBoys = grades => (
grades.filter(isBoy)
)
let getGirls = grades => (
grades.filter(isGirl)
)
let average = grades => (
grades.reduce((acc, curr) => (
acc + curr.grade
), 0) / grades.length
)
let maxGrade = grades => (
Math.max(...grades.map(student => student.grade))
)
let minGrade = grades => (
Math.min(...grades.map(student => student.grade))
)
我寫了7個函數,每個函數都有一份工作,而且只有一份工作。
isBoy 和 isGirl 負責檢查一名學生是男孩還是女孩。
getBoys 和 getGirls 負責將所有男孩或女孩帶出教室。
maxGrade 和 minGrade 負責取得某些資料中的最高和最低等級。
最後,average負責計算一些資料的平均等級。
請注意,average 函數還不知道它要處理的資料類型。這就是構圖之美。我們可以在不同的地方重複使用我們的程式碼。我可以將此功能與其他功能一起使用。
現在,我們已經有了編寫高階函數所需的東西:
let classroomAverage = average(grades) // 10.2
let boysAverage = average(getBoys(grades)) // 7
let girlsAverage = average(getGirls(grades)) // 13.4
let highestGrade = maxGrade(grades) // 18
let lowestGrade = minGrade(grades) // 2
let highestBoysGrade = maxGrade(getBoys(grades)) // 16
let lowestBoysGrade = minGrade(getBoys(grades)) // 2
let highestGirlsGrade = maxGrade(getGirls(grades)) // 18
let lowestGirlsGrade = minGrade(getGirls(grades)) // 9
請注意,外部函數(例如average)始終將內部函數的輸出作為輸入。因此,組合的唯一條件是確保輸出和輸入匹配。
而且因為每個函數只負責一件事,所以它使我們的程式碼更容易除錯和測試。
原文出處:https://dev.to/damcosset/higher-order-functions-in-javascript-4j8b