高阶函数
高阶函数是接受其他函数作为参数或返回一个函数作为值的函数。作为参数传入的函数称为回调函数。
回调函数
回调函数是可以作为参数传递给其他函数的函数。以下是一个示例。
// 回调函数,函数名可以是任何名称
const callback = (n) => {
return n ** 2
}
// 接受其他函数作为回调的函数
function cube(callback, n) {
return callback(n) * n
}
console.log(cube(callback, 3))
返回函数
高阶函数返回一个函数作为值。
// 返回另一个函数的高阶函数
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
方法就使用了回调函数。
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))
15
上面的示例可以简化如下:
const numbers = [1, 2, 3, 4]
const sumArray = arr => {
let sum = 0
arr.forEach(function(element) {
sum += element
})
return sum
}
console.log(sumArray(numbers))
15
设置时间
在 JavaScript 中,我们可以在一定时间间隔内执行某些活动,或者可以调度(等待)某些活动执行。
setInterval
setTimeout
使用 setInterval 函数设置间隔
在 JavaScript 中,我们使用 setInterval
高阶函数在一定时间间隔内持续执行某些活动。setInterval
全局方法接受一个回调函数和一个持续时间作为参数。持续时间以毫秒为单位,回调函数将在该时间间隔内被调用。
// 语法
function callback() {
// 代码在这里
}
setInterval(callback, duration)
function sayHello() {
console.log('Hello')
}
setInterval(sayHello, 1000) // 每秒打印一次 "Hello",1000ms 为 1s
使用 setTimeout 设置时间
在 JavaScript 中,我们使用 setTimeout
高阶函数在未来的某个时间执行某个动作。setTimeout
全局方法接受一个回调函数和一个持续时间作为参数。持续时间以毫秒为单位,回调函数将在该时间之后执行。
// 语法
function callback() {
// 代码在这里
}
setTimeout(callback, duration) // 持续时间以毫秒为单位
function sayHello() {
console.log('Hello')
}
setTimeout(sayHello, 2000) // 等待 2 秒后打印 "Hello"
函数式编程
在 JavaScript 的最新版本中,引入了许多内置方法,帮助我们解决复杂问题,而不需要编写常规的循环。这些内置方法都接受回调函数。在这一部分,我们将看到 forEach
、map
、filter
、reduce
、find
、every
、some
和 sort
。
forEach
forEach
:迭代数组元素。我们仅在数组上使用 forEach
。它接受一个带有元素、索引和数组自身的回调函数。索引和数组是可选的。
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))
let sum = 0;
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => console.log(num))
console.log(sum)
1
2
3
4
5
let sum = 0;
const numbers = [1, 2, 3, 4, 5];
numbers.forEach(num => sum += num)
console.log(sum)
15
const countries = ['芬兰', '丹麦', '瑞典', '挪威', '冰岛']
countries.forEach((element) => console.log(element.toUpperCase()))
FINLAND
DENMARK
SWEDEN
NORWAY
ICELAND
map
map
:迭代数组元素并修改数组元素。它接受一个带有元素、索引和数组参数的回调函数,并返回一个新数组。
const modifiedArray = arr.map(function (element, index, arr) {
return element
})
// 箭头函数和显式返回
const modifiedArray = arr.map((element, index) => element);
// 示例
const numbers = [1, 2, 3, 4, 5]
const numbersSquare = numbers.map((num) => num * num)
console.log(numbersSquare)
[1, 4, 9, 16, 25]
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const namesToUpperCase = names.map((name) => name.toUpperCase())
console.log(namesToUpperCase)
['ASABENEH', 'MATHIAS', 'ELIAS', 'BROOK']
const countries = [
'阿尔巴尼亚',
'玻利维亚',
'加拿大',
'丹麦',
'埃塞俄比亚',
'芬兰',
'德国',
'匈牙利',
'爱尔兰',
'日本',
'肯尼亚',
]
const countriesToUpperCase = countries.map((country) => country.toUpperCase())
console.log(countriesToUpperCase)
['ALBANIA', 'BOLIVIA', 'CANADA', 'DENMARK', 'ETHIOPIA', 'FINLAND', 'GERMANY', 'HUNGARY', 'IRELAND', 'JAPAN', 'KENYA']
const countriesFirstThreeLetters = countries.map((country) =>
country.toUpperCase().slice(0, 3)
)
["ALB", "BOL", "CAN", "DEN", "ETH", "FIN", "GER", "HUN", "IRE", "JAP", "KEN"]
filter
filter
:筛选出满足条件的项目并返回一个新数组。
// 筛选出包含 land 的国家
const countriesContainingLand = countries.filter((country) =>
country.includes('land')
)
console.log(countriesContainingLand)
['芬兰', '爱尔兰']
const countriesEndsByia = countries.filter((country) => country.endsWith('ia'))
console.log(countriesEndsByia)
['阿尔巴尼亚', '玻利维亚', '埃塞俄比亚']
const countriesHaveFiveLetters = countries.filter(
(country) => country.length === 5
)
console.log(countriesHaveFiveLetters)
['日本', '肯尼亚']
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)
[{name: 'Asabeneh', score: 95}, { name: 'Lidiya', score: 98 },{name: 'Martha', score: 85},{name: 'John', score: 100}]
reduce
reduce
:reduce
接受一个回调函数。回调函数接受累加器、当前值和可选的初始值作为参数,并返回一个单一值。为累加器值定义初始值是一个好习惯。如果不指定该参数,默认情况下,累加器将获得数组的第一个值。如果数组为空,JavaScript 将抛出错误。
arr.reduce((acc, cur)
=> {
// 在返回值之前执行一些操作
return
}, initialValue)
const numbers = [1, 2, 3, 4, 5]
const sum = numbers.reduce((acc, cur) => acc + cur, 0)
console.log(sum)
15
every
every
:检查所有元素在某一方面是否相同。返回布尔值。
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const areAllStr = names.every((name) => typeof name === 'string') // 所有都是字符串吗?
console.log(areAllStr)
true
const bools = [true, true, true, true]
const areAllTrue = bools.every((b) => b === true) // 所有都是 true 吗?
console.log(areAllTrue) // true
true
find
find
:返回第一个满足条件的元素。
const ages = [24, 22, 25, 32, 35, 18]
const age = ages.find((age) => age < 20)
console.log(age)
18
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const result = names.find((name) => name.length > 7)
console.log(result)
Asabeneh
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)
{ name: "Asabeneh", score: 95 }
findIndex
findIndex
:返回第一个满足条件的元素的位置。
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
:检查是否有某些元素在某一方面相同。返回布尔值。
const names = ['Asabeneh', 'Mathias', 'Elias', 'Brook']
const bools = [true, true, true, true]
const areSomeTrue = bools.some((b) => b === true)
console.log(areSomeTrue) // true
const areAllStr = names.some((name) => typeof name === 'number') // 所有都是字符串吗?
console.log(areAllStr) // false
sort
sort
:排序方法按照升序或降序排列数组元素。默认情况下,sort()
方法将值视为字符串。这对于字符串数组项来说效果良好,但对数字不适用。如果数字值按字符串排序,会导致错误的结果。排序方法会修改原始数组。在使用 sort
方法之前,建议先复制原始数据。
排序字符串值
const products = ['牛奶', '咖啡', '糖', '蜂蜜', '苹果', '胡萝卜']
console.log(products.sort()) // ['苹果', '胡萝卜', '咖啡', '蜂蜜', '牛奶', '糖']
// 现在原始产品数组也被排序了
排序数字值
如下面的示例所示,100 在升序排列后排在首位。sort
会将项目转换为字符串,因为 ‘100’ 和其他数字进行比较时,字符串 ‘100’ 的开头的 ‘1’ 被视为最小值。为避免这种情况,我们在 sort
方法内部使用一个比较回调函数,返回负数、零或正数。
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]
排序对象数组
每当我们对数组中的对象进行排序时,我们使用对象键进行比较。以下是示例。
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) // 升序排序
// [{…}, {…}, {…}, {…}]