# JavaScript教程 - 11 函数进阶
# 11.1 高阶函数
什么是高阶函数?
满足以下两种情况之一的函数就是高阶函数:
- 函数作为参数传入
- 函数作为返回值返回
高阶函数有什么作用呢?
高阶函数能让你写出更简洁、可复用、模块化的代码,它是回调函数、事件处理、函数组合等场景的核心。
下面慢慢讲。
# 1 函数作为参数
例如,我们现在有一个学生列表:
class Student {
constructor(name, chinese, math, english) {
this.name = name;
this.chinese = chinese;
this.math = math;
this.english = english;
}
}
// 学生列表
const allStuList = [
new Student("zhangsan", 87, 48, 92),
new Student("lisi", 47, 92, 71),
new Student("wangwu", 58, 46, 38),
new Student("zhangliu", 95, 91, 99),
];
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
现在分别想查询列表中:语文成绩不及格的同学、所有课程不及格的同学、所有课程都是优秀的学生,那么我们需要定义三个函数,如下:
// 学生列表
const allStuList = [
new Student("zhangsan", 87, 48, 92),
new Student("lisi", 47, 92, 71),
new Student("wangwu", 58, 46, 38),
new Student("zhangliu", 95, 91, 99),
];
// 获取语文成绩不及格的同学
function getChineseFlunkList() {
const stuList = [];
for (let stu of allStuList) {
if (stu.chinese < 60) {
stuList.push(stu);
}
}
return stuList;
}
// 获取所有课程不及格的同学
function getFlunkList() {
const stuList = [];
for (let stu of allStuList) {
if (stu.chinese < 60 && stu.math < 60 && stu.english < 60) {
stuList.push(stu);
}
}
return stuList;
}
// 获取所有课程都是优秀的学生
function getExcellentList() {
const stuList = [];
for (let stu of allStuList) {
if (stu.chinese >= 90 && stu.math >= 90 && stu.english >= 90) {
stuList.push(stu);
}
}
return stuList;
}
// -------------方法调用---------------------
console.log("语文不及格的同学:");
const chineseFlunkList = getChineseFlunkList();
for (let stu of chineseFlunkList) {
console.log(stu);
}
console.log("所有不及格的同学:");
const flunkList = getFlunkList();
for (let stu of flunkList) {
console.log(stu);
}
console.log("所有成绩都是优秀的同学:");
const excellentList = getExcellentList();
for (let stu of excellentList) {
console.log(stu);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
- 在上面的代码中,定义了3个函数
getChineseFlunkList()
、getFlunkList()
、getExcellentList()
,但是三个函数中只有其中的判断条件不同,代码比较冗余, 能否抽出判断条件,将判断条件作为参数传递呢?
我们先抽出一个公共的函数,根据传递的参数条件获取学生列表的函数:
// 根据条件获取学生列表
function filter(funCondition) {
const stuList = [];
for (let stu of allStuList) {
if (funCondition(stu)) {
stuList.push(stu);
}
}
return stuList;
}
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
- 上面的函数的参数也是一个函数,在函数中,调用传递的函数,根据函数的结果判断
stu
是否满足条件。 - 这样就可以传递一个函数,具体判断的条件,在传递的函数中实现就可以了,返回
true
就是满足条件。
下面来调用上面的函数:
// 使用示例
console.log("语文不及格的同学:");
const chineseFlunkList = filter((stu) => {return stu.chinese < 60});
for (let stu of chineseFlunkList) {
console.log(stu);
}
1
2
3
4
5
6
2
3
4
5
6
调用函数,并传递一个函数作为参数,为了简单,直接传递一个箭头函数就可以了。
stu.chinese < 60
表示如果学生的中文成绩大于60就返回true,那么在filter()
函数中调用传递的函数,就可以根据结果筛选学生了。
箭头函数还可以再简化一下,获取三个学习列表,可以这样写:
// 使用示例
console.log("语文不及格的同学:");
const chineseFlunkList = filter((stu) => stu.chinese < 60);
for (let stu of chineseFlunkList) {
console.log(stu);
}
console.log("所有不及格的同学:");
const flunkList = filter(
(stu) => stu.chinese < 60 && stu.math < 60 && stu.english < 60
);
for (let stu of flunkList) {
console.log(stu);
}
console.log("所有成绩都是优秀的同学:");
const excellentList = filter(
(stu) => stu.chinese >= 90 && stu.math >= 90 && stu.english >= 90
);
for (let stu of excellentList) {
console.log(stu);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
通过函数式编程,代码的冗余度降低了,代码更简洁了。
这种方式更符合编程的 OCP (Open-Closed Principle)原则,对扩展开放,对修改关闭。如果有其他的查询学生的条件,直接扩展即可,不用修改 filter()
函数。
# 2 函数作为返回值
函数作为返回值也经常被用到。
内容未完......
← 10-数组 12-对象和数组补充 →