Difference between $.data('foo') and $.attr('data-foo') in jQuery

10 June 2012   8 comments   Javascript


Powered by Fusion×

I learned something today thanks to my colleague Axel Hecht; the difference between $element.data('foo') and $element.attr('data-foo').

Basically, the .data() getter/setter is more powerful since it can do more things. For example:

<img id="image" data-number="42">
// numbers are turned to integers
assert($('#image').data('number') + 1 == 43);
// the more rudimentary way
assert($('#image').attr('data-number') + 1 == '421');

Integers is just one thing the .data() getter is able to parse. It can do other cool things too like booleans and JSON. Check out its docs

So, why would you NOT use .data()?

One reason is that with .data(name, value) the original DOM element is not actually modified. This can cause trouble if other pieces of Javascript depend on the value of a data- attribute further along in the page rendering process.

To see it in action check out: test.html

In conclusion: just be aware of it. Feel free to use the .data() getter/setter because it's way better but be aware of the potential risks.


Actually the main difference is that data() is a way to store data for an element. This data is a JS variable. Which means reading from it and writing to it is faster cause it doesn't live in the DOM.

attr() on the other hand is a way to access attributes on nodes.

And it happens that data() will go check if the correspondent data-attribute exists when initialising the value.
Jurriaan Persyn
Be careful with .data(), it will also convert strings to numbers it shouldn't/can't convert, and silently fail.
If you put a 64-bit integer in a data html-attribute, jQuery will see it as a number (and thus cast it to a number), although Javascript doesn't support 64-bit integers. The result will be a completely different number, without any warning.

An example: If you have a twitter uid, save it in a data-twitter-uid-attribute and fetch that with jQuery.data('twitter-uid'), you'll get a faulty result, because a twitter uid exceeds Javascript's integer size limit.
Dominic Watson
Yes, the real risk is using attr('data-foo') to read the data. Better to always use .data('foo') to read it.
Peter Bengtsson
Check what Jurriaan wrote above. There are risks with reading with .data()
Dominic Watson
That's depressing (the comment was not visible when I posted). Good to know though. You might want to wrap the logic in your own getData() method should you really never want to directly expect that there is an html attribute. Something along the lines of (untested):

$.fn.getData( function( attr ){
 if ( this.attr( 'data-' + attr ) ) {
   return this.attr( 'data-' + attr );

 return this.data( attr );
} );

This way, data could be set on the element as either an attribute or using .data() and you run no risk of expecting either one when you want to read the data back.
Dominic Watson
Or, indeed, a somewhat tidier version:

$.fn.getData( function( attr ){
 return this.attr( 'data-' + attr ) || this.data( attr );
} );
Bane Georgievski
If your data attr held a json object you might want to check first.

function isJson(str) {
    try {
    } catch (e) {
        return str;
    return JSON.parse(str);

$.fn.getDataAttr = function( attr ){
 if ( this.attr( 'data-' + attr ) ) {
   return isJson(this.attr( 'data-' + attr ));
 return this.data( attr );

These 2 functions will ensure that you get the data back properly .
Live long and prosper!
Allan Bonadio
You can just stick another parameter onto a node, if you don't need to set it in the html. eg:
node.something = '23skidoo';
> '23skidoo'
Just don't trample on the stuff that needs to be there.

Your email will never ever be published

Related posts

How I deal with deferred image loading in Javascript 08 June 2012
Newfound love of @staticmethod in Python 02 July 2012
Related by keywords:
RequireJS versus HeadJS 09 January 2011
django-html-validator 20 October 2014
All your images are belong to data uris 06 January 2013
Why I gave up on JQuery UI's autocomplete 20 October 2010
Lesson learnt with creating DOM element with jQuery 04 April 2008
jQuery and Highslide JS 08 January 2008
In jQuery, using the :visible selector can be dangerous 14 September 2010
EmailInput HTML5 friendly for Django 02 August 2011
Why Django and Grok matters 02 February 2008
A script tag's type in HTML5 10 May 2011
QUnit testing my jQuery Mobile site in full swing 17 March 2011
JetBlue a good and bad website 22 February 2007