函数是一等公民
- 函数可以存储在变量中
- 函数可以作为参数
- 函数可以作为返回值
在 Javascript 中函数就是一个普通的对象 其表现形式为 可以通过 new Function() 创建一个函数,函数可以被存储到变量/数组中,它还可以作为另一个函数的参数和返回值,甚至可以在程序运行的过程中通过 可以通过 new Function() 来构造一个新的函数。
代码演示
// 把函数赋值给变量
let fn = function () {
console.log("函数是一等公民");
};
fn(); // 函数是一等公民
这里我们定义了一个变量 fn ,并且把一个函数赋值给了 fn 然后我们通过调用 fn 打印了一句话
高阶函数
什么是高阶函数
-
可以把函数作为参数传递给另一个函数
-
可以把函数作为另一个函数的返回结果
函数作为参数
// 高阶函数-函数作为参数
// forEach
function forEach(arr, fn) {
for (let i = 0; i < arr.length; i++) {
fn(arr[i]);
}
}
// 测试
// let arr = [1, 2, 3, 4, 5, 6, 7, 8]
// forEach(arr, function (item) {
// console.log(item);
// })
// filter
function filter(arr, fn) {
let results = [];
for (let i = 0; i < arr.length; i++) {
if (fn(arr[i])) results.push(arr[i]);
}
return results;
}
// 测试
// let arr = [1, 2, 3, 4, 5, 6, 7, 8];
// let result = filter(arr, function (item) {
// return item % 2 === 0;
// });
// console.log(result);
函数作为参数的优点
- 函数变得更灵活:可通过函数作为参数的形式,使另一个函数变得更通用
- 函数内部细节被屏蔽:如上面示例
forEach,filter通过名字就可以知道函数的功能。直接只调用即可
函数作为返回值
用一个函数生成一个函数
基础示例
function makeFn() {
let msg = "hello fn";
return function () {
console.log(msg);
};
}
const fn = makeFn();
fn();
makeFn()();
生成一个只执行一次的函数
// once 生成一个只执行一次的函数
function once(fn) {
let done = false; // 记录fn是否执行
return function () {
if (!done) {
done = true;
fn.apply(this, arguments); // arguments指的上一行这个函数的参数
}
};
}
// 测试
let pay = once(function (money) {
console.log(`支付了:${money} RMB`);
});
pay(5); // 打印 支付了:5 RMB, 此处的入参5就是上面 arguments
pay(6); // 不会执行
pay(3); // 不会执行
使用高阶函数的意义
抽象可以帮我们屏蔽细节,只需要关注我们的目标
我们知道函数式编程就是对运算过程进行抽象,把运算过程抽象成函数。我们就可以在需要使用这个函数功能的地方直接进行调用。
高阶函数就是用来抽象通用的问题
比如上面的 forEach 函数 我们不需要关注循环的具体实现和细节。只需要知道 forEach 帮我们完成了循环就可以了,并且代码更加清晰、简洁。
常用的高阶函数
- forEach
- map
- filter
- every
- some
- find/findIndex
- reduce
- sort
- ......
map 对数组的每一个元素进行遍历,并对每个元素进行处理,并返回处理的结果集
// map 对数组的每一个元素进行遍历,并对每个元素进行处理,并返回处理的结果集
const map = (arr, fn) => {
let results = [];
for (const val of arr) {
results.push(fn(val));
}
return results;
};
// 测试
let arr = [1, 2, 3, 4];
arr = map(arr, (v) => v * v); // 可以指定第二个参数,做任何事情。甚至可以上天
console.log(arr);
every 数组中每个元素是否都满足我们指定的条件
// every 数组中每个元素是否都满足我们指定的条件
const every = (arr, fn) => {
let result = true;
for (const val of arr) {
result = fn(val);
if (!result) break;
}
return result;
};
// 测试
let arr = [4, 5, 6];
let bool = every(arr, (v) => v > 3);
console.log(bool); // true
let arr = [2, 5, 6];
let bool = every(arr, (v) => v > 3);
console.log(bool); // false
some 数组中是否有一个元素是否都满足我们指定的条件
// some 数组中是否有一个元素是否都满足我们指定的条件
const some = (arr, fn) => {
let result = false;
for (const val of arr) {
result = fn(val);
if (result) break;
}
return result;
};
// 测试
let arr = [1, 3, 6];
let bool = some(arr, (v) => v % 2 === 0); // 数组中是否有偶数
console.log(bool); // true
let arr = [1, 3, 7];
let bool = some(arr, (v) => v % 2 === 0);
console.log(bool); // false