高阶函数(higher-order-function)并不是 JavaScript 语言所特有的东西,它适用于整个计算机领域,甚至数学领域。
满足以下任一条件的函数都被称为高阶函数:
- 函数可以作为参数被传递(callback)或者说接收一个或多个函数作为输入
- 函数可以作为返回值输出(closer)
JavaScript 中的函数显然满足高阶函数的条件,在实际开发中,无论是将函数当作参数传递,还是让函数的执行结果返回另外一个函数,这两种情形都有很多应用场景。
函数是一等公民
在函数提升和变量提升的部分我们已知“函数是一等公民”这个说法了,当变量提升和函数提升同时存在,函数提升会在变量提升之前。函数可以像其他数据类型一样进入任何场所,可以:
- 被保存到变量中 let foo = function(){ }
- 作为参数传递 arr.sort( (a, b) => a-b )
- 作为返回值返回 closer ```javascript // 使用函数表达式定义函数,相当于是将函数保存到变量中 let foo = function(i){ … }
// 函数可以在变量之间传递,就像其他数据类型一样 let bar = foo;
// 函数可以当作参数直接传递 login(bar);
// 函数可以作为返回值返回,和其他数据类型一样 function foo(){ function random(){…} return random; }
<a name="N4xbA"></a>
## 函数作为参数传递
把函数当作参数传递,代表可以抽离出一部分容易变化的业务逻辑,把这部分业务逻辑放在函数参数中,这样一来可以分离业务代码中 **变化 **与 **固定 **的部分。其中一个常见的应用场景就是回调函数。
<a name="lOOxq"></a>
### 排序
对于数组的 sort() 方法想必已经非常熟悉了,该方法就接收一个函数作为参数。从 sort() 方法的使用可以看到,我们的目的是对数组进行排序,这是不变的部分;而使用什么规则去排序,则是可变的部分。<br />把可变的部分封装在函数参数里,动态传入 sort() 方法,使 sort() 函数成为了一个非常灵活的方法,所以 sort() 就属于一个高阶函数。
如果只是对数组中的数字进行排序就简单了:
```javascript
arr.sort((a, b) => a - b);
在对扑克牌排序需求:当点数相等时,按花色排:
arr.sort((a, b) => {
if(a.number == b.number){
return a.flower - b.flower;
}else{
return a.number - b.number;
}
});
自定义高阶函数
首先思考一下高阶函数的所需要素,无非就是参数中需要一个函数,那如果代码写作:
function repeat(count, fn) {
for (let i = 0; i < count; i++) {
fn(); // 打印5次 被调用
}
}
repeat(5, foo);
function foo() {
console.log('被调用');
}
如果再换种方式玩这个函数:
function repeat(count, fn) {
for (let i = 0; i < count; i++) {
fn();
}
}
repeat(10, function () {
console.log("hello");
}); // 输出 10 个 hello
这种写法在哪里见过吗?addEventListener( ) 或者 setInterval( )中就见过这个写法对不对!
返回值输出
将函数作为返回值输出,看起来无非就是 return 出一个 function 咯?
// 该函数没有任何实际的意义,仅仅是一个 demo
function foo(){
return function(a, b){
console.log(a + b);
}
}
当函数被调用:
let add = foo(); // 调用 foo 后接受到返回值 function
add(1, 2); // 3
add('hello', 'world'); // hello world
(找个什么很厉害的封面图呢…害)