Using jQuery's datastore vs. expando properties

后端 未结 4 1735
我在风中等你
我在风中等你 2021-01-31 20:22

I\'m developing code using jQuery and need to store data associated with certain DOM elements. There are a bunch of other questions about how to store arbitrary data w

相关标签:
4条回答
  • 2021-01-31 20:54

    Using $.data will protect you from memory leaks.

    In IE, when you assign a javascript object to an expando property on a DOM element, cycles that cross that link are not garbage collected. If your javascript object holds a reference to the dom object, the whole cycle will leak. It's entirely possible to end up with hidden references to DOM objects, due to closures, so you may leak without realizing it.

    The jQuery datastore is set up to prevent these cycles from forming. If you use it, you will not leak memory in this way. Your example will not leak because you are putting primitives (strings) on the DOM element. But if you put a more complex object there, you risk leaking.

    Use $.data so you won't have to worry.

    0 讨论(0)
  • 2021-01-31 21:04

    Using $.data doesn't modify the DOM. You should use $.data. If you're creating a plugin then you should store one object in $.data with properties on that object as opposed to storing each of those properties as different key/value pairs in the $.data structure.

    0 讨论(0)
  • 2021-01-31 21:07

    Let me rephrase the question: What are the practical differences between the two data binding options available?

    Actually there are three options:

    $(e).prop('myKey', myValue);
    $(e).data('myKey', myValue);
    $(e).attr('data-myKey', myValue);
    

    Note: OP’s e.myKey = myValue is practically the same as the .prop() line.

    • if you need more than strings, use .prop(), i.e. expando properties
    • if you need DOM/CSS transparency and/or HTML serialization use .attr('data-*')
    • if you need both you are out of luck
    • if you only use strings, but need no DOM, read on to weigh pros and cons yourself
    • what is with .data() → read the last two paragraphs

    If you ever want to pass the data around with serialized HTML you need the .attr() solution. I.e. whenever you use things like .innerHTML or .html() or want to construct snippets from strings with data included. The same applies if you want to use CSS selectors like elem[data-myKey]. Disadvantage: you can only store strings.

    If you don’t need your data to be visible in the DOM or available to CSS interaction .data() and .prop() might work. Their biggest advantage is: they can hold any Javascript value.

    .prop() biggest disadvantage is the possibility of name collision. Only pick names you can be sure will not be used as native property ever. E.g. scope as key is a bad idea, because it exists on some HTML elements...

    Now comes .data(). The other answers seem to swear on it, I avoid it. The memory leaks related to .prop() and expando properties in general belong to the past, so that is no advantage any more. But you will be secured against name collisions with HTML properties. That is an advantage. But you get a bunch of disadvantages:

    $(e).data('myKey') draws its uninitialized value from the data-myKey attribute if available, runs JSON.parse() on those and sometimes returns that or falls back to the string value of the attribute. Once you set $(e).data('myKey', myValue) you lose the relationship with the data-myKey attribute, which nevertheless lives on with its “old” value, shown in DOM and in CSS interactions. On top, the key name you use is subject to possible name mangling. I.e. if you ever decide to read all key-value via $(e).data() the keys in that object might be different.

    Because of this erratic behavior (mixing expando property technology with data-* attributes) and inconsistent get/set design I always avoid .data().—Fortunately that is easy to do with .prop() and .attr() (with data-* keys for compliance).

    If you really want to use .data() to avoid name clashes with native properties, my advice: do not mix with data-* attributes, consider them a different thing, and avoid name clashes with those.—Does that make sense? For automatic clash avoidance you have to avoid clashes elsewhere manually. Great design.

    0 讨论(0)
  • 2021-01-31 21:09

    If you are authoring a plugin you should use $.data. If you need to store the attribute often and rarely need to query the DOM for it then use $.data.

    Update 5 years later: jQuery does not query the DOM based on expando properties set, and hasn't done so for a while. So use $.data. There's no reason to pollute the DOM when there is no pragmatic use to do so.

    0 讨论(0)
提交回复
热议问题