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);
}
}
這樣,“復雜”方法可以在沒有外部依賴的情況下單獨測試,并且您有一個使用該方法的實現。
添加回答
舉報