# 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.weight, 0)
//33

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

for(i=0;i<str.length;i++){
var chr = str.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)