4

Is there a way to create WeakMap of any other weak references in Javascript for storing key value pairs where key is String/Number and value is Object.

The referencing would have to work something like this:

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     

I creating kind of a tree structure that holds track of references that are still used in the current scope.

I will do a lot of merging, and recursively cleaning up a deeply nested structure can be very inefficient for this use case.

2 Answers 2

5

You can solve it by using WeakRef and FinalizationRegistry.

Here is an example written in 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()

It must be run with the --expose-gc option in the node.js environment.

Sign up to request clarification or add additional context in comments.

2 Comments

That's a nice example! Lot of new features in JavaScript since 5 years ago when I was trying to find a solution for this=). Here is a codepen of the code example above codepen.io/jEnbuska/pen/jOxzZbm
There is a bug: let a = {}, b = {}; const wm = new InvertedWeakMap(); wm.set('key', a); wm.set('key', b); a = null; system.gc(); console.info(wm.has('key'));
1

You cannot catch a delete operation. What you could do would be encapsuling the data in another obj e.g.

function referenceTo(value){
 this.value=value;
}

So if this one reference is deleted, it cant be accessed anymore

var somedata=new referenceTo(5)
var anotherref=somedata;
//do whatever
delete somedata.value;
//cannot be accessed anymore
anotherref.value;//undefined

2 Comments

To my understanding that does not solve the issue of deleting nested structures when top one is deleted? ps. I fixed the example, the previous was invalid. I don't get it why es6 WeakMap does not take strings as keys and objects as values. Doesn't seem to add any value on everyday programming.
@nabuska yeah you may need to filter somewhen.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.