摘自:https://muyiy.vip/blog/6/6.1.html
## 高阶函数
高阶函数英文叫 Higher-order function,它的定义很简单,就是至少满足下列一个条件的函数:
* 接受一个或多个函数作为输入
* 输出一个函数
也就是说高阶函数是对其他函数进行操作的函数,可以将它们作为参数传递,**或者**是返回它们。 简单来说,高阶函数是一个接收函数作为参数传递**或者**将函数作为返回值输出的函数。
## 函数作为参数传递
JavaScript 语言中内置了一些高阶函数,比如 Array.prototype.map,Array.prototype.filter 和 Array.prototype.reduce,它们接受一个函数作为参数,并应用这个函数到列表的每一个元素。我们来看看使用它们与不使用高阶函数的方案对比。
### Array.prototype.map
`map()`方法创建一个新数组,其结果是该数组中的每个元素都调用一个**提供的函数**后返回的结果,**原始数组不会改变**。传递给 map 的回调函数(`callback`)接受三个参数,分别是 currentValue、index(可选)、array(可选),除了`callback`之外还可以接受 this 值(可选),用于执行`callback`函数时使用的`this`值。
来个简单的例子方便理解,现在有一个数组`[1, 2, 3, 4]`,我们想要生成一个新数组,其每个元素皆是之前数组的两倍,那么我们有下面两种使用高阶和不使用高阶函数的方式来实现。
#### 不使用高阶函数
~~~
const arr1 = [1, 2, 3, 4];
const arr2 = [];
for (let i = 0; i < arr1.length; i++) {
arr2.push( arr1[i] * 2);
}
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]
~~~
#### 使用高阶函数
~~~
const arr1 = [1, 2, 3, 4];
const arr2 = arr1.map(item => item * 2);
console.log( arr2 );
// [2, 4, 6, 8]
console.log( arr1 );
// [1, 2, 3, 4]
~~~
### Array.prototype.filter
`filter()`方法创建一个新数组, 其包含通过提供函数实现的测试的所有元素,**原始数组不会改变**。接收的参数和 map 是一样的,其返回值是一个新数组、由通过测试的所有元素组成,如果没有任何数组元素通过测试,则返回空数组。
来个例子介绍下,现在有一个数组`[1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]`,我们想要生成一个新数组,这个数组要求没有重复的内容,即为去重。
#### 不使用高阶函数
~~~
const arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
const arr2 = [];
for (let i = 0; i < arr1.length; i++) {
if (arr1.indexOf( arr1[i] ) === i) {
//索引为2,即i=2; arr1.indexOf( arr1[i] )=1,第一个1
arr2.push( arr1[i] );
}
}
console.log( arr2 );
// [1, 2, 3, 5, 4]
console.log( arr1 );
// [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]
~~~
#### 使用高阶函数
~~~
const arr1 = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];
const arr2 = arr1.filter( (element, index, self) => {
return self.indexOf( element ) === index;
});
console.log( arr2 );
// [1, 2, 3, 5, 4]
console.log( arr1 );
// [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4]
~~~
### add 函数
用 JS 实现一个无限累加的函数`add`:
```
function add(a) {
function sum(b) { // 使用闭包
a = a + b; // 累加
return sum;
}
sum.toString = function() { // 重写toString()方法
return a;
}
return sum; // 返回一个函数
}
add(1)(2)(3)(4) // 10
```