Вы просто не можете использовать собственный Map
, поскольку он обеспечивает только обязательный интерфейс.
Вы можете обратиться к библиотеке с открытым исходным кодом, такой как популярный Immutable JS.
или Вы можете написать свои собственные постоянные (неизменяемые) структуры данных. Основным требованием является то, что операции, предоставляемые вашей структурой данных , не изменяют входные данные. Вместо этого новая структура данных возвращается с каждой операцией -
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" ] }
// {}