Vanilla alternative to jQuery $ .data () function: any native javascript alternative?

Usually I don’t need to include the jQuery library in my scripts, however, I just recently came across jQuery $ .data () functions that can bind data in the form of pairs of key values, objects and even functions to any element,

From what I read, the jQuery $ .data () function also has built-in precautions that prevent memory leaks associated with such methods, but it overflows to include the entire JQ library for this single function.

Does anyone know of a native alternative?

EDIT To make it clearer, I'm not looking for a native function to retrieve the attributes of an element. The jQuery $ .data () API goes far beyond such use, expanding its ability to associate javascript objects and functions with jQuery element nodes.

This article ( http://tutorialzine.com/2010/11/jquery-data-method/ ) addresses this use, but as an example I use it to associate a GSAP Timeline animation with an object so that I can access and call the GSAP Timeline.reverse () function of the animation outside the function that it created. For instance:

function doAnimation(){ var element = document.createElement('div'), timeline = new TimelineMax({....GSAP related fns...}), options = { .... timeline: timeline }; $(element).data('options', options); } function reverseAnimation($element){ var options = $element.data('options'), previouslyCreatedTimeline = options.timeline; previouslyCreatedTimeline.reverse(); } 

It may not be the most vivid example if you are not a GSAP user, but in fact, the $ .data () method allowed me to associate a javascript object with an element so that I could access its methods in a function outside its original scope.

+9
source share
5 answers

I wrote a wrapper around WeakMap and Map that should do the job. A nice feature of WeakMap is that the value gets GarbageCollected after the item is deleted. This should avoid memory leaks.

 /** A storage solution aimed at replacing jQuerys data function. * Implementation Note: Elements are stored in a (WeakMap)[https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap]. * This makes sure the data is garbage collected when the node is removed. */ window.dataStorage = { _storage: new WeakMap(), put: function (element, key, obj) { if (!this._storage.has(element)) { this._storage.set(element, new Map()); } this._storage.get(element).set(key, obj); }, get: function (element, key) { return this._storage.get(element).get(key); }, has: function (element, key) { return this._storage.has(element) && this._storage.get(element).has(key); }, remove: function (element, key) { var ret = this._storage.get(element).delete(key); if (!this._storage.get(element).size === 0) { this._storage.delete(element); } return ret; } } 

Use it like this:

 var myElement = document.getElementById("myId"); dataStorage.put(myElement, "myKey", "myValue"); 

This is much faster than $ .data (), but still a bit slower than storing information as an element property.

+9
source

You can store anything on any DOM element:

 // store data: document.body.data = {a:1, b:2}; // retrieve data: console.log(document.body.data); 

I used the word data here as a custom DOM property, but it can be any word that is not yet in use.


jQuery does not store things on the elements themselves, because it can lead to memory leaks, but since you need it for a very specific task, then it will work. Just make sure you know how a memory leak occurs before you try.

Other answers mention the data HTML attribute. This has nothing to do with jQuery data . Absolutely nothing, and it also requires you to analyze and plan your data (if this is not a string).

+4
source

See the following general data function. Use $.data(obj) to get all metadata associated with any object, $.data(obj, key) to get metadata with a given key associated with an object, and $.data(obj, key, val) , to set metadata with a given key for an object. Problems may arise with conflicts of attributes of native objects, for example, setting something with the key 'toString' or 'hasOwnProperty' .

 window.$ = { data: function(obj, key, val) { if(!obj) { return this._data; } else if(!key) { if(!(obj in this._data)) { return {}; } return this._data[obj]; } else if(arguments.length < 3) { if(!(obj in this._data)) { return undefined; } return this._data[obj][key]; } else { if(!(obj in this._data)) { this._data[obj] = {}; } this._data[obj][key] = val; } }, _data: {} }; 

Here is an example of how it is used:

 $.data(document.body); // Returns {} because no data has been set for this object $.data(document.body, 'lastUpdate', new Date());//Sets 'lastUpdate' of obj to current time $.data(document.body, 'lastUpdate'); // Gets previously set time $.data(document.body); // Gets object of all data, including 'lastUpdate' time $.data(document.body, 'nonexistant'); // Returns undefined because property was never set $.data(); // Returns all metadata 
+2
source

Use the setAttribute method:

 document.getElementById('item1').setAttribute('data', "icon: 'base2.gif', url: 'output.htm', target: 'AccessPage', output: '1'"); 

But you really should use the data following the dash and with your property, for example:

 <li ... data-icon="base.gif" ...> 

And for this in JS use the dataset property:

 document.getElementById('item1').dataset.icon = "base.gif"; 
+1
source

For simple key storage, use a .dataset , which reflects the data-* attributes of the element. However, it is limited to string values, so you need to serialize composite values ​​(e.g. using JSON ).

To store references to objects and functions, I would recommend using WeakMap . He will take care to avoid memory leaks. In a browser that does not support this, just save them as a direct property in the html element, but be careful to choose name names without conflict.

+1
source

Source: https://habr.com/ru/post/1215951/


All Articles