摘自: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
```