2 回答

TA贡献1797条经验 获得超6个赞
您根本无法使用本机Map,因为它仅提供命令式接口。
您可以使用开源库,例如流行的 ImmutableJS。
或者您可以编写自己的持久(不可变)数据结构。基本要求是您的数据结构提供的操作不会修改输入。相反,每个操作都会返回一个新的数据结构 -
const PersistentMap =
{ create: () =>
({})
, set: (t = {}, key, value) =>
({ ...t, [key]: value }) // <-- immutable operation
}
我们首先看一张empty地图,一个set操作的结果,然后确保empty地图没有被修改——
const empty =
PersistentMap.create()
console.log
( empty
, PersistentMap.set(empty, "hello", "world")
, empty
)
// {}
// { hello: "world" }
// {}
现在让我们看一个新的中间状态,m1。每次我们看到set返回一个新的持久映射并且不修改输入 -
const m1 =
PersistentMap.set(empty, "hello", "earth")
console.log
( m1
, PersistentMap.set(m1, "stay", "inside")
, m1
)
// { hello: "earth" }
// { hello: "earth", stay: "inside" }
// { hello: "earth" }
现在回答你的问题,我们可以添加一个push操作到我们的PersitentMap- 我们只需要确保我们不修改输入。这是一种可能的实现-
const PersistentMap =
{ // ...
, push: (t = {}, key, value) =>
PersistentMap.set // <-- immutable operation
( t
, key
, Array.isArray(t[key])
? [ ...t[key], value ] // <-- immutable operation
: [ value ]
)
}
我们push在下面看到行动。请注意,m2也不会empty因此而改变 -
const m2 =
PersistentMap.push(empty, "fruits", "apple")
console.log
( m2
, PersistentMap.push(m2, "fruits", "peach")
, m2
, empty
)
// { fruits: [ "apple" ] }
// { fruits: [ "apple", "peach" ] }
// { fruits: [ "apple" ] }
// {}
展开下面的代码段以在您自己的浏览器中验证结果
const PersistentMap =
{ create: () =>
({})
, set: (t = {}, key, value) =>
({ ...t, [key]: value })
, push: (t = {}, key, value) =>
PersistentMap.set
( t
, key
, Array.isArray(t[key])
? [ ...t[key], value ]
: [ value ]
)
}
const empty =
PersistentMap.create()
console.log
( empty
, PersistentMap.set(empty, "hello", "world")
, empty
)
// {}
// { hello: "world" }
// {}
const m1 =
PersistentMap.set(empty, "hello", "earth")
console.log
( m1
, PersistentMap.set(m1, "stay", "inside")
, m1
)
// { hello: "earth" }
// { hello: "earth", stay: "inside" }
// { hello: "earth" }
const m2 =
PersistentMap.push(empty, "fruits", "apple")
console.log
( m2
, PersistentMap.push(m2, "fruits", "peach")
, m2
, empty
)
// { fruits: [ "apple" ] }
// { fruits: [ "apple", "peach" ] }
// { fruits: [ "apple" ] }
// {}

TA贡献1805条经验 获得超9个赞
我认为这取决于你想要达到的目标。如果您希望您的代码是可测试的,FP 并不总是意味着只需要编写函数,您仍然可以使用类,但是如果您有一段复杂的代码要单独测试,您可以导出该代码段进行测试,并且它看起来像这样:
// types.ts
type FooDis = Record<string, object[]>;
// addBarToFoos.ts
export const addBarToFoos = (foos: FooDis) => (key: string, bar: object): FooDis {
foos = {
...foos,
[key]: [
...foos[key],
bar
]
};
return foos;
}
// FooClass.ts
export class FooClass {
private foos: FooDis = {};
addBar(key: string, bar: object) {
this.foos = addBarToFoos(this.foos)(key, bar);
}
}
这样,“复杂”方法可以在没有外部依赖的情况下单独测试,并且您有一个使用该方法的实现。
添加回答
举报