Open lingxiao-Zhu opened 3 years ago
组合单元 | 函数 | 对象、类 |
---|---|---|
编程风格 | 声明式 | 命令式 |
数据和行为 | 独立且松耦合的纯函数 | 与方法紧耦合的类 |
状态管理 | 将对象是为不可变的值 | 主张通过实例方法改变对象 |
程序流控制 | 函数与递归 | 循环与条件判断 |
线程安全 | 可并发编程 | 难以实现 |
封装性 | 因为一切不可变,不需要封装 | 需要保护数据的完整性 |
基本概念:声明式编程、纯函数、引用透明、不可变性
FP中,很少会用this,事实上,应该不惜一切代价来避免使用它。
程序为实现业务目标所要行进的路径被称为控制流。
函数即数据,因为FP是声明式的,它描述了数据输出是什么,而不是数据是如何得到的。
ES6带来的尾调用优化,可以使递归和迭代的性能表现更加接近,将递归调用作为函数体最后的步骤。递归本质上是一种循环操作。纯粹的函数式编程语言没有循环操作命令,所有的循环都用递归实现,这就是为什么尾递归对这些语言极其重要。
函数式编程将管道视为构建程序的唯一方法。
除了能够有效提升代码的可重用性外,将多元函数转换为一元函数才是柯里化的主要动机。
由于数据不经意地变成来null或者undefined,出现来异常、失去网络连接等情况,代码需要顾及此类问题,所有要花大量的代码来确保所有抛出的异常都能被适当的捕获,并且在所有能想到的地方检查值是否为null,最后的结果就是代码越来越长、不能扩展,推理起来费劲。
显然使用try-catch后的代码将不能组合或连在一起。函数式程序不应抛出异常。
FP不会加快单个函数的求值速度。相反,它的理念是避免重复的函数调用以及延迟调用代码,把求值延迟到必要的时候,这可以使程序整体加速,在纯FP语言中,平台内置来这些优化,然而在js中,需要开发者来做。
在JS中,每个函数调用其实都会在函数上下文堆栈中创建栈帧。,栈是一个基本的数据结构,它的插入和取出顺序是后进先出,LIFO。
柯里化和递归会造成大量上下文堆栈的开销,嵌套结构的函数会使用更多的堆栈。
只有将函数的上下文状态作为参数传递给下一个函数调用,才能使递归调用不依赖当前帧,通过这种方式,递归每次都会创建一个新的帧,回收旧的帧,这就是尾递归优化。
FP的柯里化可以实现OOP中的工厂方法。
// OOP
interface Store {
getItem(key: string): string;
}
class WebStore implements Store{
getItem(key: string){
return localstorage.getItem(key);
};
}
class WxStore implements Store{
getItem(key: string){
return wx.getStorageSync(key);
};
}
const store = new xxxStore();
store.find(xxx);
// FP
const getFromWebStore = () => {
return (key)=>{
return localstorage.getItem(key)
}
}
const getFromWxStore = () => {
return (key)=>{
return wx.getStorageSync(key)
}
}
const find = getFromXXXStore();
find(xxx);