DEV Community

Sarsa Murmu
Sarsa Murmu

Posted on

How to save data for a HTML element in JavaScript

If you've worked with vanilla DOM manipulation, you've probably found yourself in a situation when you have to save data associated with an element. Let's see how we can do this.

For the first time, you probably came up with the idea to save the data on the element object itself, like this

const setElementData = (el, data) => {
  el.$dataKey = data;
}

const getElementData = (el) => {
  return el.$dataKey;
}

// Usage
setElementData(document.querySelector('#some-el'), {
  prop1: 'val',
  prop2: someComplexValue
});

// Somewhere
const elData = getElementData(document.querySelector('#some-el'));
Enter fullscreen mode Exit fullscreen mode

Even if this method works, it's not good. Adding custom props to an element object is not recommended and it can cause memory leaks if not done correctly.

So, what's the correct way to do it?

The correct way is to use a WeakMap to store data for an element. The code will look like this

const elementDataMap = new WeakMap();

const setElementData = (el, data) => {
  elementDataMap.set(el, data);
}

const getElementData = (el) => {
  return elementDataMap.get(el);
}

// Usage
setElementData(document.querySelector('#some-el'), {
  prop1: 'val',
  prop2: someComplexValue
});

// Somewhere
const elData = getElementData(document.querySelector('#some-el'));
Enter fullscreen mode Exit fullscreen mode

This way we are able to save data for an element without causing memory leaks. If you don't know what WeakMap is, check out the MDN docs.

See ya!

Top comments (3)

Collapse
 
michaelcurrin profile image
Michael Currin • Edited

In Python there is weakref too by the way but of course won't help with the DOM

docs.python.org/3/library/weakref....

Several built-in types such as list and dict do not directly support weak references but can add support through subclassing:

class Dict(dict):
    pass

obj = Dict(red=1, green=2, blue=3)   # this object is weak referenceable
Collapse
 
michaelcurrin profile image
Michael Currin • Edited

Thanks for sharing. I hadn't heard of WeakMap.
I think your two get and set functions, in both cases, add unnecessary complexity and the built methods can make it clearer.

This below is much easier to follow for me and avoids relying on functions to have side effects on a global object.

let elementDataMap = new WeakMap()

const someEl = document.querySelector('#some-el')

elementDataMap.set(
  someEl, {
    prop1: 'val',
    prop2: someComplexValue
});

const elData = elementDataMap.get(someEl);

I can see how putting use of .$dataKey in a function can help in larger application but in the first case you could just set and get directly without the functions.

Also I think it should be mentioned that you can't use this .get on any element to find its data unless you first make a map and send data on the map.

Collapse
 
sarsamurmu profile image
Sarsa Murmu

That's good too. The main thing is the WeakMap after all, you can use it in any way you like to 😀