WeakMap перевернутый
Есть ли способ создать WeakMap из любых других слабых ссылок в Javascript для хранения пар ключ-значение, где ключ - String/Number, а значение - Object.
Ссылка должна работать примерно так:
const wMap = new WeakRefMap();
const referencer = {child: new WeakRefMap()}
wMap.set('child', temp.child);
wMap.has('child'); // true
delete referencer.child
wMap.has('child'); //false
Я создал вид древовидной структуры, которая содержит ссылки, которые все еще используются в текущей области видимости.
Я сделаю много слияний, и рекурсивная очистка глубоко вложенной структуры может быть очень неэффективной для этого варианта использования.
2 ответа
Вы можете решить эту проблему, используя WeakRef и FinalizationRegistry.
Вот пример, написанный на TypeScript:
class InvertedWeakMap<K extends string | symbol, V extends object> {
_map = new Map<K, WeakRef<V>>()
_registry: FinalizationRegistry<K>
constructor() {
this._registry = new FinalizationRegistry<K>((key) => {
this._map.delete(key)
})
}
set(key: K, value: V) {
this._map.set(key, new WeakRef(value))
this._registry.register(value, key)
}
get(key: K): V | undefined {
const ref = this._map.get(key)
if (ref) {
return ref.deref()
}
}
has(key: K): boolean {
return this._map.has(key) && this.get(key) !== undefined
}
}
async function main() {
const map = new InvertedWeakMap()
let data = { hello: "world!" } as any
map.set("string!", data)
console.log('---before---')
console.log(map.get("string!"))
console.log(map.has("string!"))
data = null
await new Promise((resolve) => setTimeout(resolve, 0))
global.gc() // call gc manually
console.log('---after---')
console.log(map.get("string!"))
console.log(map.has("string!"))
}
main()
Его необходимо запустить с параметром --expose-gc в среде node.js.
Вы не можете поймать операцию удаления. Что вы могли бы сделать, это инкапсулировать данные в другой объект, например
function referenceTo(value){
this.value=value;
}
Так что, если эта ссылка удалена, к ней больше нельзя будет получить доступ
var somedata=new referenceTo(5)
var anotherref=somedata;
//do whatever
delete somedata.value;
//cannot be accessed anymore
anotherref.value;//undefined