开始
![964bb12cc77b1559b724b645c6cccabc.png](https://i-blog.csdnimg.cn/blog_migrate/a0511ca964e9e70110cee40f16315346.jpeg)
当时看不懂,然后黏糊糊学长 @GooeyNyan 细心的讲了很久hhh
第一种方法是迭代,偏向命令式,也就是写一条条指令让计算机执行动作
每一步都有一个确定的结果,然后计算可以在每一步都可以暂停中断,也可以从任意部分再启动
第二种是用递归,偏向声明式,形成(a+b+c+d+...+0)这样的运算
更关心逻辑产生的过程.通过过程产生想要的结果
const sum1 = list =>
list.length === 0
? 0
: list[0] + sum1(list.slice(1))
const sum2 = list => list.reduce((acc,x) => acc + x)
这是求幂的例子
const pow1 = (base,count) =>
count === 0
? 1
: base * pow1(base,count-1)
const pow2 = (base,count) => {
let result = 1;
for(let i = 0;i<count;i++){
result *= base;
}
return result;
}
因为要一次一次算*base,糊糊学长还做了优化
当count是2的倍数的时候,可以直接平方
const square = x => x*x;
const pow1 = (base, count) =>
count === 0
? 1
: count % 2 === 0
? square(pow1(base, count / 2))
: base * pow1(base, count - 1)
const pow2 = (base, count) => {
let result = 1;
let i = count;
const iter = (j,res) => {
j === 0
? res
: j % 2 === 0
? iter(j/2,square(res))
: iter(j-1,res * base)
}
return iter(i,result);
}
不可变(Immutable)
函数式推崇不可变,或者说是没有变量这个概念
- 增加一点空间损耗 -> 换来可读性
const arr = [1,2,3];
arr.push(4) //normal
const brr = [...arr,4]; //better
不可变数据带来的提升:
React中的props和state是不可变的,这样能检测出前一个state和后一个是否相等,减少不必要的重绘
性能问题
justjavac:JavaScript 函数式编程存在性能问题么?在这个问题里面,for循环还是比一些遍历方法快的
随着JS引擎优化做的越来越好,遍历方法甚至已经比for循环还快,既提升了性能,可读性也变高了
![f2c6ab2de1945c33f09363bd52f03242.png](https://i-blog.csdnimg.cn/blog_migrate/412611cfc3a0878b4b3fc4e12fd5c893.jpeg)
![e5a13cd8f30f309a34f15172d3ac41d7.png](https://i-blog.csdnimg.cn/blog_migrate/3586826ad3dc8251d6ec6c52f7ffda1d.jpeg)
纯函数
函数式编程的核心是借助形式化数学描述逻辑 -> lambda运算
纯函数: 无副作用,并且输入相同的时候,输出始终保持一致
const arr = [1,2,3,4,5,6,7];
arr.slice(0,3); //[1,2,3]
arr.slice(0,3); //[1,2,3]
arr.splice(0,3) //[1,2,3]
arr.splice(0,3) //[4,5,6]
arr.splice(0,3) //[7]
显而易见,slice()是纯函数,splice()不是纯函数
纯函数带来的好处: 可以仅仅关注函数本身,不用担心外部因素的问题
const add = x => x+10;
let a = 10;
const adda = x => x+a;
const addv = x => x+v;
比如这里的add是纯函数,我不用担心程序会因为a不同而改变,但是这样写死了10,程序的拓展性会变差
解决方案:柯里化
"预加载"的函数,传递较少的参数,得到一个已经记住了这些参数的新函数 -> 达到缓存计算
const add = x => y => x+y;
let add2 = add(2);
let add10 = add2(10); //12
组合
柯里化带来的问题,容易写出f(g(h(x)))
这样的函数
const compose = (f,g) => (x => f(g(x)));
有了组合,就可以随意的拼接代码
const first = arr => arr[0];
const reverse = arr => arr.reverse();
const last = compose(reverse,first);
last([1,2,3,4,5]); //5
实现一个Compose
compose 函数 | ScriptOJscriptoj.mangojuice.topconst compose = (...funcs) => (data) => funcs.reverse().reduce((data,func) => func(data),data)
高阶函数的组合
- 之前写的OASIS小程序里面,也涉及过一点
数组的遍历方法代替loop和if,可能会增加一点可读性
// 项目管理员
let adminBrr = that.data.projectmembers
.filter(x => Number(x.clearance) >= 1)
.map(y => ({
adminName: y.realName,
adminEmail: y.email,
uid: y.uid
}));
//过滤空值
let filterArr = this.data.dateArr
.filter(items => typeof items.day === "number")
.map(item => {
item.select = false;
});
2. "乔波的招新题"
用(JAVA)JavaScript写出不显示定义变量的情况下,计算1~100中不能被3整除的数的平方和
[...Array(100).keys()]
.map(x => (x + 1) ** 2)
.filter(x => x % 3 !== 0)
.reduce((x, y) => x + y);
import java.util.stream.IntStream;
class Main{
public static void main(String[] args){
System.out.println(IntStream.range(0,101).filter(x -> x%3 != 0).map(x -> x*x).sum());
}
}