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

10 June 2012   9 comments   Javascript


Mind That Age!

This blog post is 5 years old! Most likely, its content is outdated. Especially if it's technical.

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.
Keith Lubell
Great Post. I just saw this behaviour today. Thanks
Thank you for posting a comment

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 Keyword:
Some tips on learning React 04 August 2015
django-html-validator 20 October 2014
All your images are belong to data uris 06 January 2013
Going real simple on HTML5 audio 14 October 2011
EmailInput HTML5 friendly for Django 02 August 2011
Related by Text:
Fastest database for Tornado 09 October 2013
All your images are belong to data uris 06 January 2013
One-way data bindings in AngularJS 1.3 11 December 2014
To $('#foo p') or to $('p', $('#foo')) 24 February 2009
Entering multilanguage data in Zope 26 November 2006