# Javascript函数式编程小结

### 为什么需要函数式编程

1. Less bug: 可读性高, 逻辑上更容易理解.

2. less Time: 更高的抽象层级, 代码高度可复用.

### 高阶函数(Higher-order functions)

Functions that operate on other functions, either by taking them as arguments or by returning them, are called higher-order functions.

```//把函数当成变量
var foo = (x) => console.log(x)
//把函数当作参数传入另一个函数
var bar = (y, fn) => fn(y)
foo('FP is good') // FP is good
bar('FP is great', foo) //FP is great```

```var arr = [1,1,2,3,5,8]
function traverseArray(arr) {
for (let i = 0; i < arr.length; i++) {
console.log(`index: \${i}, value: \${arr[i]}`)
}
}
traverseArray(arr)```

Easy enough! 如果用函数式编程的思维重写上面的代码应该是这个样子的:

```function forEach(arr, fn) {
for (let i = 0; i < arr.length; i++) {
fn(i, arr[i], arr)
}
}

forEach(arr, (index, value) => console.log(`index: \${index}, value: \${value}`))```

WTF!? 说好的函数式编程更简洁代码量更少呢! 明显第二种写法写的代码更多啊. 别急, 其实es5的时候JS已经把一系列高阶函数设置好了,比如 `forRach, map, reduce, filter, every..` 让我们用js的 `array.forEach` 重写上面的代码:

`arr.forEach((v, k) => console.log(`index: \${k}, value: \${v}`))`

### 常用方法举例

```var animals = [
{name: 'a' , species: 'dog', weight: 11},
{name: 'b', species: 'cat', weight: 10},
{name: 'c', species: 'fish', weight: 1},
{name: 'd', species: 'cat', weight: 8},
{name: 'e', species: 'rabbit', weight: 3}
]
// 找到所有种类为猫的动物
animals.filter((animal) => animal.species === 'cat')
// [ { name: 'b', species: 'cat' }, { name: 'd', species: 'cat' } ]

// 返回所有动物的名字
animals.map((animal) => animal.name)
// [ 'a', 'b', 'c', 'd', 'e' ]

// 最重动物的体重
animals.reduce((pre, animal) => pre + animal.amount, 0)
//11```

```// 一般做法是这样的
var str="abcdaabc"
var count = {};
var i;

for(i=0;i<str.length;i++){
var chr = arr.charAt(i);
if( typeof count[chr] === "undefined"){
count[chr] = 1;
}else{
count[chr]++;
}
}

// 利用函数式编程思想的方法是这样的
var res = str.split('')
.reduce((pre, cur) => (pre[cur]++ || (pre[cur] = 1), pre), {})```

```var fs = require('fs');
var words = content.split(/[\s.,\/:\n]+/);
// 把单词全部变为小写并利用上一个例子的方法统计单词出现的次数
var tally = words.map((word) => word.toLowerCase())
.reduce((pre, cur) => (pre[cur]++ || (pre[cur]=1), pre), {})
//把object的key变成数组并进行排序
var top10 = Object.keys(tally)
.map((key) => {
return {word: key, count: tally[key]}
})
.sort((a, b) => b.count - a.count)
.slice(0, 10)
console.log(top10)```