主题
JavaScript 高阶函数
高阶函数
高阶函数是将其他函数作为参数或返回函数作为值的函数。作为参数传递的函数称为回调函数。
回调函数
回调函数是可以作为参数传递给其他函数的函数。请看下面的例子。
js
// 回调函数,函数名可以是任何名称
const callback = (n) => {
return n ** 2
}
// 将其他函数作为回调的函数
function cube(callback, n) {
return callback(n) * n
}
console.log(cube(callback, 3))
返回函数
高阶函数返回函数作为值
js
// 返回另一个函数的高阶函数
const higherOrder = n => {
const doSomething = m => {
const doWhatEver = t => {
return 2 * n + 3 * m + t
}
return doWhatEver
}
return doSomething
}
console.log(higherOrder(2)(3)(10))
让我们看看在哪里使用回调函数。例如,forEach
方法使用回调。
js
const numbers = [1, 2, 3, 4, 5]
const sumArray = arr => {
let sum = 0
const callback = function(element) {
sum += element
}
arr.forEach(callback)
return sum
}
console.log(sumArray(numbers))
sh
15
上面的例子可以简化如下:
js
const numbers = [1, 2, 3, 4]
const sumArray = arr => {
let sum = 0
arr.forEach(function(element) {
sum += element
})
return sum
}
console.log(sumArray(numbers))
sh
15
设置时间
在 JavaScript 中,我们可以在特定的时间间隔内执行某些活动,或者我们可以安排(等待)一段时间来执行某些活动。
- setInterval
- setTimeout
使用 setInterval 函数设置间隔
在 JavaScript 中,我们使用 setInterval 高阶函数在某个时间间隔内连续执行某些活动。setInterval 全局方法接受回调函数和持续时间作为参数。持续时间以毫秒为单位,回调将始终在该时间间隔内被调用。
js
// 语法
function callback() {
// 代码在这里
}
setInterval(callback, duration)
js
function sayHello() {
console.log('Hello')
}
setInterval(sayHello, 1000) // 每秒打印 hello,1000ms 是 1s
使用 setTimeout 设置时间
在 JavaScript 中,我们使用 setTimeout 高阶函数在将来的某个时间执行某些操作。setTimeout 全局方法接受回调函数和持续时间作为参数。持续时间以毫秒为单位,回调等待该时间量。
js
// 语法
function callback() {
// 代码在这里
}
setTimeout(callback, duration) // 持续时间以毫秒为单位
js
function sayHello() {
console.log('Hello')
}
setTimeout(sayHello, 2000) // 等待 2 秒后打印 hello
函数式编程
JavaScript 的最新版本引入了许多内置方法,可以帮助我们解决复杂的问题,而不是编写常规循环。所有内置方法都接受回调函数。在本节中,我们将看到 forEach
、map
、filter
、reduce
、find
、every
、some
和 sort
。
forEach
forEach
:迭代数组元素。我们只对数组使用 forEach
。它接受一个带有元素、索引参数和数组本身的回调函数。索引和数组是可选的。
js
arr.forEach(function (element, index, arr) {
console.log(index, element, arr)
})
// 上面的代码可以使用箭头函数编写
arr.forEach((element, index, arr) => {
console.log(index, element, arr)
})
// 上面的代码可以使用箭头函数和显式返回编写
arr.forEach((element, index, arr) => console.log(index, element, arr))
js
let sum = 0;
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => console.log(num))
console.log(sum)
sh
1
2
3
4
5
js
let sum = 0;
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => sum += num)
console.log(sum)
sh
15
js
const countries = ['Finland', 'Denmark', 'Sweden', 'Norway', 'Iceland']
countries.forEach((element) => console.log(element.toUpperCase()))
sh
FINLAND
DENMARK
SWEDEN
NORWAY
ICELAND
map
map
:迭代数组元素并修改数组元素。它接受一个带有元素、索引、数组参数的回调函数并返回一个新数组。
js
const modifiedArray = arr.map(function (element, index, arr) {
return element
})
js
/*箭头函数和显式返回
const modifiedArray = arr.map((element,index) => element);
*/
//示例
const numbers = [1, 2, 3, 4, 5]
const numbersSquare = numbers.map((num) => num * num)
console.log(numbersSquare)
sh
[1, 4, 9, 16, 25]
js
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const namesToUpperCase = names.map((name) => name.toUpperCase())
console.log(namesToUpperCase)
sh
['ASABENEH', 'MATHIAS', 'ELIAS', 'BROOK']
js
const countries = [
'Albania',
'Bolivia',
'Canada',
'Denmark',
'Ethiopia',
'Finland',
'Germany',
'Hungary',
'Ireland',
'Japan',
'Kenya',
]
const countriesToUpperCase = countries.map((country) => country.toUpperCase())
console.log(countriesToUpperCase)
/*
// 箭头函数
const countriesToUpperCase = countries.map((country) => {
return country.toUpperCase();
})
//显式返回箭头函数
const countriesToUpperCase = countries.map(country => country.toUpperCase());
*/
sh
['ALBANIA', 'BOLIVIA', 'CANADA', 'DENMARK', 'ETHIOPIA', 'FINLAND', 'GERMANY', 'HUNGARY', 'IRELAND', 'JAPAN', 'KENYA']
js
const countriesFirstThreeLetters = countries.map((country) =>
country.toUpperCase().slice(0, 3)
)
sh
["ALB", "BOL", "CAN", "DEN", "ETH", "FIN", "GER", "HUN", "IRE", "JAP", "KEN"]
filter
filter
:过滤出满足过滤条件的项目并返回一个新数组。
js
//过滤包含 land 的国家
const countriesContainingLand = countries.filter((country) =>
country.includes('land')
)
console.log(countriesContainingLand)
sh
['Finland', 'Ireland']
js
const countriesEndsByia = countries.filter((country) => country.endsWith('ia'))
console.log(countriesEndsByia)
sh
['Albania', 'Bolivia','Ethiopia']
js
const countriesHaveFiveLetters = countries.filter(
(country) => country.length === 5
)
console.log(countriesHaveFiveLetters)
sh
['Japan', 'Kenya']
js
const scores = [
{ name: 'Asabeneh', score: 95 },
{ name: 'Lidiya', score: 98 },
{ name: 'Mathias', score: 80 },
{ name: 'Elias', score: 50 },
{ name: 'Martha', score: 85 },
{ name: 'John', score: 100 },
]
const scoresGreaterEighty = scores.filter((score) => score.score > 80)
console.log(scoresGreaterEighty)
sh
[{name: 'Asabeneh', score: 95}, { name: 'Lidiya', score: 98 },{name: 'Martha', score: 85},{name: 'John', score: 100}]
reduce
reduce
:reduce 接受一个回调函数。回调函数接受累加器、当前值和可选的初始值作为参数,并返回单个值。为累加器值定义初始值是一个好习惯。如果我们不指定此参数,默认情况下累加器将获得数组的第一个值。如果我们的数组是空数组,那么 JavaScript 将抛出错误。
js
arr.reduce((acc, cur) => {
// 在返回值之前进行一些操作
return
}, initialValue)
js
const numbers = [1, 2, 3, 4, 5]
const sum = numbers.reduce((acc, cur) => acc + cur, 0)
console.log(sum)
js
15
every
every
:检查所有元素在某一方面是否相似。它返回布尔值
js
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const areAllStr = names.every((name) => typeof name === 'string') // 都是字符串吗?
console.log(areAllStr)
sh
true
js
const bools = [true, true, true, true]
const areAllTrue = bools.every((b) => b === true) // 都是 true 吗?
console.log(areAllTrue) // true
sh
true
find
find
:返回满足条件的第一个元素
js
const ages = [24, 22, 25, 32, 35, 18]
const age = ages.find((age) => age < 20)
console.log(age)
js
18
js
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const result = names.find((name) => name.length > 7)
console.log(result)
sh
Asabeneh
js
const scores = [
{ name: 'Asabeneh', score: 95 },
{ name: 'Mathias', score: 80 },
{ name: 'Elias', score: 50 },
{ name: 'Martha', score: 85 },
{ name: 'John', score: 100 },
]
const score = scores.find((user) => user.score > 80)
console.log(score)
sh
{ name: "Asabeneh", score: 95 }
findIndex
findIndex
:返回满足条件的第一个元素的位置
js
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const ages = [24, 22, 25, 32, 35, 18]
const result = names.findIndex((name) => name.length > 7)
console.log(result) // 0
const age = ages.findIndex((age) => age < 20)
console.log(age) // 5
some
some
:检查某些元素在某一方面是否相似。它返回布尔值
js
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const bools = [true, true, true, true]
const areSomeTrue = bools.some((b) => b === true)
console.log(areSomeTrue) //true
js
const areAllStr = names.some((name) => typeof name === 'number') // 都是字符串吗?
console.log(areAllStr) // false
sort
sort
:sort 方法按升序或降序排列数组元素。默认情况下,sort()
方法将值作为字符串排序。这对字符串数组项目很有效,但对数字无效。如果数字值作为字符串排序,它会给我们错误的结果。Sort 方法修改原始数组。建议在开始使用 sort 方法之前复制原始数据。
排序字符串值
js
const products = ['Milk', 'Coffee', 'Sugar', 'Honey', 'Apple', 'Carrot']
console.log(products.sort()) // ['Apple', 'Carrot', 'Coffee', 'Honey', 'Milk', 'Sugar']
//现在原始 products 数组也被排序了
排序数字值
如您在下面的示例中所见,100 在按升序排序后排在第一位。Sort 将项目转换为字符串,由于 '100' 和其他数字比较,字符串 '100' 开头的 1 成为最小的。为了避免这种情况,我们在 sort 方法内部使用比较回调函数,它返回负数、零或正数。
js
const numbers = [9.81, 3.14, 100, 37]
// 使用 sort 方法对数字项目排序提供错误的结果。见下文
console.log(numbers.sort()) //[100, 3.14, 37, 9.81]
numbers.sort(function (a, b) {
return a - b
})
console.log(numbers) // [3.14, 9.81, 37, 100]
numbers.sort(function (a, b) {
return b - a
})
console.log(numbers) //[100, 37, 9.81, 3.14]
排序对象数组
每当我们对数组中的对象进行排序时,我们使用对象键进行比较。让我们看看下面的例子。
js
objArr.sort(function (a, b) {
if (a.key < b.key) return -1
if (a.key > b.key) return 1
return 0
})
// 或
objArr.sort(function (a, b) {
if (a['key'] < b['key']) return -1
if (a['key'] > b['key']) return 1
return 0
})
const users = [
{ name: 'Asabeneh', age: 150 },
{ name: 'Brook', age: 50 },
{ name: 'Eyob', age: 100 },
{ name: 'Elias', age: 22 },
]
users.sort((a, b) => {
if (a.age < b.age) return -1
if (a.age > b.age) return 1
return 0
})
console.log(users) // 按升序排序
// [{…}, {…}, {…}, {…}]
🌕 你做得很好。永远不要放弃,因为伟大的事情需要时间。你刚刚完成了第9天的挑战,你在通往伟大的道路上前进了9步。现在为你的大脑和肌肉做一些练习。
💻 练习
练习:级别 1
js
const countries = ['Finland', 'Sweden', 'Denmark', 'Norway', 'IceLand']
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
const products = [
{ product: 'banana', price: 3 },
{ product: 'mango', price: 6 },
{ product: 'potato', price: ' ' },
{ product: 'avocado', price: 8 },
{ product: 'coffee', price: 10 },
{ product: 'tea', price: '' },
]
- 解释
forEach
、map
、filter
和reduce
之间的区别。 - 在 forEach、map、filter 或 reduce 中使用回调函数之前定义它。
- 使用
forEach
在控制台记录 countries 数组中的每个国家。 - 使用
forEach
在控制台记录 names 数组中的每个名字。 - 使用
forEach
在控制台记录 numbers 数组中的每个数字。 - 使用
map
通过将 countries 数组中的每个国家更改为大写来创建新数组。 - 使用
map
从 countries 数组创建国家长度数组。 - 使用
map
通过将 numbers 数组中的每个数字更改为平方来创建新数组 - 使用
map
将 names 数组中的每个名字更改为大写 - 使用
map
将 products 数组映射到其相应的价格。 - 使用
filter
过滤出包含land
的国家。 - 使用
filter
过滤出有六个字符的国家。 - 使用
filter
过滤出在 country 数组中包含六个字母及以上的国家。 - 使用
filter
过滤出以 'E' 开头的国家; - 使用
filter
过滤出只有值的价格。 - 声明一个名为 getStringLists 的函数,它接受一个数组作为参数,然后返回一个只包含字符串项的数组。
- 使用
reduce
对 numbers 数组中的所有数字求和。 - 使用
reduce
连接所有国家并产生这个句子:Estonia, Finland, Sweden, Denmark, Norway, and IceLand are north European countries
- 解释
some
和every
之间的区别 - 使用
some
检查 names 数组中是否有一些名字的长度大于七 - 使用
every
检查所有国家是否都包含单词 land - 解释
find
和findIndex
之间的区别。 - 使用
find
在 countries 数组中找到第一个只包含六个字母的国家 - 使用
findIndex
在 countries 数组中找到第一个只包含六个字母的国家的位置 - 使用
findIndex
找到Norway
的位置,如果它在数组中不存在,你将得到 -1。 - 使用
findIndex
找到Russia
的位置,如果它在数组中不存在,你将得到 -1。
练习:级别 2
- 通过链接两个或多个数组迭代器找到产品的总价格(例如 arr.map(callback).filter(callback).reduce(callback))
- 仅使用 reduce 找到产品价格的总和 reduce(callback))
- 声明一个名为
categorizeCountries
的函数,它返回具有某些共同模式的国家数组(你在此存储库中找到 countries 数组作为 countries.js(例如 'land'、'ia'、'island'、'stan'))。 - 创建一个函数,返回一个对象数组,这是字母和字母用于以国家名称开头的次数。
- 声明一个
getFirstTenCountries
函数并返回十个国家的数组。使用不同的函数式编程在 countries.js 数组上工作 - 声明一个
getLastTenCountries
函数,它返回 countries 数组中的最后十个国家。 - 找出哪个字母作为国家名称的首字母使用了很多次(例如 Finland、Fiji、France 等)
练习:级别 3
使用 data 文件夹中的 countries 信息。按名称、首都、人口对国家进行排序
*** 找到 10 种最常用的语言:
js// 你的输出应该看起来像这样 console.log(mostSpokenLanguages(countries, 10)) [ {country: 'English',count:91}, {country: 'French',count:45}, {country: 'Arabic',count:25}, {country: 'Spanish',count:24}, {country:'Russian',count:9}, {country:'Portuguese', count:9}, {country:'Dutch',count:8}, {country:'German',count:7}, {country:'Chinese',count:5}, {country:'Swahili',count:4} ] // 你的输出应该看起来像这样 console.log(mostSpokenLanguages(countries, 3)) [ {country: 'English',count: 91}, {country: 'French',count: 45}, {country: 'Arabic',count: 25}, ]
*** 使用 countries_data.js 文件创建一个函数,创建十个人口最多的国家
jsconsole.log(mostPopulatedCountries(countries, 10)) [ {country: 'China', population: 1377422166}, {country: 'India', population: 1295210000}, {country: 'United States of America', population: 323947000}, {country: 'Indonesia', population: 258705000}, {country: 'Brazil', population: 206135893}, {country: 'Pakistan', population: 194125062}, {country: 'Nigeria', population: 186988000}, {country: 'Bangladesh', population: 161006790}, {country: 'Russian Federation', population: 146599183}, {country: 'Japan', population: 126960000} ] console.log(mostPopulatedCountries(countries, 3)) [ {country: 'China', population: 1377422166}, {country: 'India', population: 1295210000}, {country: 'United States of America', population: 323947000} ]
*** 尝试开发一个程序,计算样本的集中趋势测量(均值、中位数、众数)和变异性测量(范围、方差、标准差)。除了这些测量之外,还要找到样本的最小值、最大值、计数、百分位数和频率分布。你可以创建一个名为 statistics 的对象,并创建所有进行统计计算的函数作为 statistics 对象的方法。检查下面的输出。
jsconst ages = [31, 26, 34, 37, 27, 26, 32, 32, 26, 27, 27, 24, 32, 33, 27, 25, 26, 38, 37, 31, 34, 24, 33, 29, 26] console.log('Count:', statistics.count()) // 25 console.log('Sum: ', statistics.sum()) // 744 console.log('Min: ', statistics.min()) // 24 console.log('Max: ', statistics.max()) // 38 console.log('Range: ', statistics.range() // 14 console.log('Mean: ', statistics.mean()) // 30 console.log('Median: ',statistics.median()) // 29 console.log('Mode: ', statistics.mode()) // {'mode': 26, 'count': 5} console.log('Variance: ',statistics.var()) // 17.5 console.log('Standard Deviation: ', statistics.std()) // 4.2 console.log('Variance: ',statistics.var()) // 17.5 console.log('Frequency Distribution: ',statistics.freqDist()) # [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
shconsole.log(statistics.describe()) Count: 25 Sum: 744 Min: 24 Max: 38 Range: 14 Mean: 30 Median: 29 Mode: (26, 5) Variance: 17.5 Standard Deviation: 4.2 Frequency Distribution: [(20.0, 26), (16.0, 27), (12.0, 32), (8.0, 37), (8.0, 34), (8.0, 33), (8.0, 31), (8.0, 24), (4.0, 38), (4.0, 29), (4.0, 25)]
🎉 恭喜!🎉