函子即容器
函子即一个持有值的普通对象(可以由类实现),具有map
方法。遍历每一个值并产生一个新的函子对象。
🍐 简单实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class Container { constructor(value) { this.value = value }
map(fn) { return Container.of(fn(this.value)) }
static of(value) { return new this(value) } }
|
🍐 Pointed 函子
函子只是一个实现了map
方法的对象,而 of
静态方法属于 Pointed
函子的实现
🌰 函子使用
1 2 3 4 5 6 7
| const double = (n) => n * 2
const n = new Container(2) .map(double) .map(double)
console.log(n)
|
🍐 MayBe 函子
MayBe
函子是在普通函子的基础上对错误进行了抽象处理,将对map
处理的值进行进行判空(null
| undefined
)处理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| class MayBe { constructor(value) { this.value = value }
map(fn) { return MayBe.of(this.isNothing() ? null : fn(this.value)) }
isNothing() { return this.value === null || this.value === undefined }
static of(value) { return new this(value) } }
|
🌰 MayBe函子 使用
1 2 3 4 5 6 7
| const strVal = new MayBe('cool').map((v) => v.toUpperCase())
const emptyVal = new MayBe(null).map((v) => v.toUpperCase())
new MayBe(null).map((v) => v.toUpperCase()).map((v) => `val: ${v}`)
|
🌰 MayBe函子 处理混合类型的数据
调用接口可能会返回 情况1
, 情况2
, 情况3
的数据,想获取到返回数据children
最后一章的id。就可以使用 MayBe
函子
1 2 3 4 5 6 7 8 9 10 11 12
| const result1 = { data: { id: 1, title: '书名', children: [ { name: '章节1', id: 101 }, { name: '章节2', id: 102 }, { name: '章节3', id: 103 }, { name: '章节4', id: 104 }, ], }, }
|
1 2 3 4 5 6 7
| const result2 = { data: { id: 2, title: '书名', children: [], }, }
|
1 2 3 4
| const result3 = { data: {}, errorCode: '空空如也', }
|
🌰 使用函子去获取最后一个章节的id
1 2 3 4 5 6 7 8 9 10 11 12 13
| const getLastChildId = (result) => { return new MayBe(result) .map((result) => result.data) .map((data) => data.children) .map((children) => children[children.length - 1]) .map((item) => item.id) }
const lastId1 = getLastChildId(result1) const lastId2 = getLastChildId(result2) const lastId3 = getLastChildId(result3)
|
在JavaScript中亦存在函子的设计,按F12
在控制台尝试输入 new Array(6).map(v => console.log(v)
试试 console.log
是否执行了