函子01-maybe Pointed

2.3k words

函子即容器

函子即一个持有值的普通对象(可以由类实现),具有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))
}

/**
* 静态方法,接受一个值并返回新的函子容器
* 具有 of 静态方法的可以称为 Pointed 函子
* */
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) // Container { value: 4 }
.map(double) // Container { value: 8 }

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()) // MayBe { value: "COOL" }

// map 中的方法并没有并执行
const emptyVal = new MayBe(null).map((v) => v.toUpperCase()) // MayBe { value: null }

// 方法大胆用,只有存有值才会执行
new MayBe(null).map((v) => v.toUpperCase()).map((v) => `val: ${v}`)

🌰 MayBe函子 处理混合类型的数据

调用接口可能会返回 情况1, 情况2, 情况3 的数据,想获取到返回数据children最后一章的id。就可以使用 MayBe 函子

  • 情况1:预期数据
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 },
],
},
}
  • 情况2: children为空
1
2
3
4
5
6
7
const result2 = {
data: {
id: 2,
title: '书名',
children: [],
},
}
  • 情况3:获取到空数据
1
2
3
4
const result3 = {
data: {},
errorCode: '空空如也',
}

🌰 使用函子去获取最后一个章节的id

1
2
3
4
5
6
7
8
9
10
11
12
13
/** 获取最后一个章节的id */
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) // MayBe { value: 104 }
const lastId2 = getLastChildId(result2) // MayBe { value: null }
const lastId3 = getLastChildId(result3) // MayBe { value: null }

在JavaScript中亦存在函子的设计,按F12在控制台尝试输入 new Array(6).map(v => console.log(v) 试试 console.log 是否执行了