函数式编程是一种编程范式,强调使用函数和避免状态变化和可变数据。以下是函数式编程要掌握的一些关键知识点:
1. 纯函数
定义:纯函数是指给定相同的输入总是返回相同的输出,并且没有任何可观察的副作用。
示例:
const add = (a, b) => a + b;
2. 不可变性
定义:不可变性指的是数据一旦创建就不能被修改。任何修改数据的操作都会返回一个新的数据副本。
示例:
const arr = [1, 2, 3]; const newArr = [...arr, 4]; // 使用扩展运算符创建新数组
3. 高阶函数
定义:高阶函数是指接受一个或多个函数作为参数,或返回一个函数作为结果的函数。
示例:
const map = (fn, arr) => arr.map(fn);
4. 函数组合
定义:函数组合是将多个函数组合成一个函数,其中每个函数的输出作为下一个函数的输入。
示例:
const compose = (f, g) => x => f(g(x));
5. 柯里化
定义:柯里化是将一个多参数函数转换为一系列单参数函数的过程。
示例:
const add = a => b => a + b; const addFive = add(5); console.log(addFive(3)); // 输出 8
6. 递归
定义:递归是函数调用自身的技术,用于解决问题的分解。
示例:
const factorial = n => (n === 0 ? 1 : n * factorial(n - 1));
7. 惰性求值
定义:惰性求值是指表达式在需要时才计算,而不是在定义时计算。
示例:
const lazyValue = () => 2 + 2;
8. 不可变数据结构
定义:使用不可变数据结构来避免状态变化。
示例:
const obj = { a: 1 };const newObj = { ...obj, b: 2 }; // 使用扩展运算符创建新对象
9. Monad
定义:Monad 是一种设计模式,用于处理函数式编程中的副作用。
示例:
class Maybe { constructor(value) { this.value = value; } static of(value) { return new Maybe(value); } map(fn) { return this.value ? Maybe.of(fn(this.value)) : Maybe.of(null); } }
10. 尾递归优化
定义:尾递归优化是一种优化技术,用于优化递归函数的性能。
示例:
const factorial = (n, acc = 1) => (n === 0 ? acc : factorial(n - 1, n * acc));
11. 函数签名
定义:函数签名描述了函数的输入和输出类型,有助于理解函数的行为和用途。
示例:
// TypeScript 示例
const add: (a: number, b: number) => number = (a, b) => a + b;
12. 部分应用
定义:部分应用是指固定一个函数的一些参数,生成一个新的函数。
示例:
const add = (a, b) => a + b; const addFive = add.bind(null, 5); console.log(addFive(3)); // 输出 8
13. Point-Free 风格
定义:Point-Free 风格是一种编写函数的方式,不显式地提及函数的参数。
示例:
const add = (a, b) => a + b; const increment = add.bind(null, 1);
14. Functor
定义:Functor 是一个实现了
map
方法的容器类型,用于在容器内应用函数。示例:
class Functor { constructor(value) { this.value = value; } map(fn) { return new Functor(fn(this.value)); } }
15. Applicative
定义:Applicative 是一种 Functor,它不仅可以在容器内应用函数,还可以在容器内应用多个参数。
示例:
class Applicative extends Functor { ap(f) { return f.map(this.value); } }
16. Foldable
定义:Foldable 是一种数据结构,可以被折叠(或归约)成一个单一的值。
示例:
const sum = (arr) => arr.reduce((acc, val) => acc + val, 0);
17. Traversable
定义:Traversable 是一种数据结构,可以被遍历并应用函数,结果仍然是一个 Traversable。
示例:
const traverse = (fn, arr) => arr.map(fn);
18. 管道操作
定义:管道操作是一种将多个函数按顺序组合起来的方式,每个函数的输出作为下一个函数的输入。
示例:
const pipe = (...fns) => (x) => fns.reduce((v, f) => f(v), x);
19. 代数数据类型(ADT)
定义:代数数据类型是一种复合类型,通过组合其他类型来构建。
示例:
// TypeScript 示例 type Option<T> = Some<T> | None; class Some<T> { constructor(public value: T) {} } class None {}
20. 模式匹配
定义:模式匹配是一种检查数据结构并根据其形状执行代码的技术。
示例:
// TypeScript 示例 const match = (value) => ({ Some: (fn) => (value instanceof Some ? fn(value.value) : match(value)), None: (fn) => (value instanceof None ? fn() : match(value)), run: () => value, });
21. 记忆化
定义:记忆化是一种优化技术,通过缓存函数的计算结果来避免重复计算。
示例:
const memoize = (fn) => { const cache = {}; return (...args) => { const key = JSON.stringify(args); if (!cache[key]) { cache[key] = fn(...args); } return cache[key]; }; };
22. 惰性求值
定义:惰性求值是一种计算策略,只有在需要时才计算表达式的值。
示例:
const lazyValue = () => 2 + 2;
23. 流(Streams)
定义:流是一种处理数据序列的抽象,可以按需生成和处理数据。
示例:
const stream = require('stream'); const readable = new stream.Readable({ read() { this.push('data'); this.push(null); } }); readable.on('data', (chunk) => { console.log(chunk.toString()); });
24. 事件驱动编程
定义:事件驱动编程是一种编程范式,程序的执行流由事件触发。
示例:
const EventEmitter = require('events'); const emitter = new EventEmitter(); emitter.on('event', () => { console.log('An event occurred!'); }); emitter.emit('event');
25. 代数效应
定义:代数效应是一种处理副作用的方式,通过将副作用抽象为可组合的操作。
26. 类型系统
定义:类型系统用于定义和检查程序中的数据类型,确保类型安全。
示例:
// TypeScript 示例
const add = (a: number, b: number): number => a + b;
27. 类型类
定义:类型类是一种抽象,定义了一组操作,这些操作可以应用于多种类型。
示例:
// TypeScript 示例
interface Functor<T> { map<U>(fn: (x: T) => U): Functor<U>; }
29. 类型推断
定义:类型推断是编译器自动推断表达式类型的能力。
示例:
// TypeScript 示例
let x = 3; // x 被推断为 number 类型
30. 类型别名
定义:类型别名用于为复杂类型定义一个简短的名称。
示例:
// TypeScript 示例 type Point = { x: number; y: number }; const point: Point = { x: 1, y: 2 };
掌握这些知识点将帮助你更深入地理解和应用函数式编程。