In response to my answer yesterday about rotating an Image, Jamund told me to use .data()
instead of .attr()
First I thought that he is right, but then I thought about a bigger context... Is it always better to use .data()
instead of .attr()
? I looked in some other posts like what-is-better-data-or-attr or jquery-data-vs-attrdata
The answers were not satisfactory for me...
So I moved on and edited the example by adding CSS. I thought it might be useful to make a different Style on each image if it rotates. My style was the following:
.rp[data-rotate="0"] {
border:10px solid #FF0000;
}
.rp[data-rotate="90"] {
border:10px solid #00FF00;
}
.rp[data-rotate="180"] {
border:10px solid #0000FF;
}
.rp[data-rotate="270"] {
border:10px solid #00FF00;
}
Because design and coding are often separated, it could be a nice feature to handle this in CSS instead of adding this functionality into JavaScript. Also in my case the data-rotate
is like a special state which the image currently has. So in my opinion it make sense to represent it within the DOM.
I also thought this could be a case where it is much better to save with .attr()
then with .data()
. Never mentioned before in one of the posts I read.
But then i thought about performance. Which function is faster? I built my own test following:
<!DOCTYPE HTML>
<html>
<head>
<title>test</title>
<script type="text/javascript" src=".7.1/jquery.min.js"></script>
<script type="text/javascript">
function runfirst(dobj,dname){
console.log("runfirst "+dname);
console.time(dname+"-attr");
for(i=0;i<10000;i++){
dobj.attr("data-test","a"+i);
}
console.timeEnd(dname+"-attr");
console.time(dname+"-data");
for(i=0;i<10000;i++){
dobj.data("data-test","a"+i);
}
console.timeEnd(dname+"-data");
}
function runlast(dobj,dname){
console.log("runlast "+dname);
console.time(dname+"-data");
for(i=0;i<10000;i++){
dobj.data("data-test","a"+i);
}
console.timeEnd(dname+"-data");
console.time(dname+"-attr");
for(i=0;i<10000;i++){
dobj.attr("data-test","a"+i);
}
console.timeEnd(dname+"-attr");
}
$().ready(function() {
runfirst($("#rp4"),"#rp4");
runfirst($("#rp3"),"#rp3");
runlast($("#rp2"),"#rp2");
runlast($("#rp1"),"#rp1");
});
</script>
</head>
<body>
<div id="rp1">Testdiv 1</div>
<div id="rp2" data-test="1">Testdiv 2</div>
<div id="rp3">Testdiv 3</div>
<div id="rp4" data-test="1">Testdiv 4</div>
</body>
</html>
It should also show if there is a difference with a predefined data-test
or not.
One result was this:
runfirst #rp4
#rp4-attr: 515ms
#rp4-data: 268ms
runfirst #rp3
#rp3-attr: 505ms
#rp3-data: 264ms
runlast #rp2
#rp2-data: 260ms
#rp2-attr: 521ms
runlast #rp1
#rp1-data: 284ms
#rp1-attr: 525ms
So the .attr()
function did always need more time than the .data()
function. This is an argument for .data()
I thought. Because performance is always an argument!
Then I wanted to post my results here with some questions, and in the act of writing I pared with the questions Stack Overflow showed me (similar titles)
And true enough, there was one interesting post about performance
I read it and run their example. And now I am confused! This test showed that .data()
is slower then .attr()
!?!! Why is that so?
First I thought it is because of a different jQuery library so I edited it and saved the new one. But the result wasn't changing...
So now my questions to you:
- Why are there some differences in the performance in these two examples?
- Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?
Now depending on the performance:
- Would performance be an argument for you using
.attr()
instead of data, if it shows that.attr()
is better? Although data is meant to be used for.data()
?
UPDATE 1:
I did see that without overhead .data()
is much faster. Misinterpreted the data :) But I'm more interested in my second question. :)
Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?
Are there some other reasons you can think of, to use .attr()
and not .data()
? e.g. interoperability? because .data()
is jquery style and HTML Attributes can be read by all...
UPDATE 2:
As we see from T.J Crowder's speed test in his answer attr
is much faster then data
! which is again confusing me :) But please! Performance is an argument, but not the highest! So give answers to my other questions please too!
UPDATE 3:
My test seems to be false because of the fire-bug I used while testing! The same file in chrome listed attr
faster and a second test on jsperf also says attr
is faster
In response to my answer yesterday about rotating an Image, Jamund told me to use .data()
instead of .attr()
First I thought that he is right, but then I thought about a bigger context... Is it always better to use .data()
instead of .attr()
? I looked in some other posts like what-is-better-data-or-attr or jquery-data-vs-attrdata
The answers were not satisfactory for me...
So I moved on and edited the example by adding CSS. I thought it might be useful to make a different Style on each image if it rotates. My style was the following:
.rp[data-rotate="0"] {
border:10px solid #FF0000;
}
.rp[data-rotate="90"] {
border:10px solid #00FF00;
}
.rp[data-rotate="180"] {
border:10px solid #0000FF;
}
.rp[data-rotate="270"] {
border:10px solid #00FF00;
}
Because design and coding are often separated, it could be a nice feature to handle this in CSS instead of adding this functionality into JavaScript. Also in my case the data-rotate
is like a special state which the image currently has. So in my opinion it make sense to represent it within the DOM.
I also thought this could be a case where it is much better to save with .attr()
then with .data()
. Never mentioned before in one of the posts I read.
But then i thought about performance. Which function is faster? I built my own test following:
<!DOCTYPE HTML>
<html>
<head>
<title>test</title>
<script type="text/javascript" src="http://ajax.googleapis./ajax/libs/jquery/1.7.1/jquery.min.js"></script>
<script type="text/javascript">
function runfirst(dobj,dname){
console.log("runfirst "+dname);
console.time(dname+"-attr");
for(i=0;i<10000;i++){
dobj.attr("data-test","a"+i);
}
console.timeEnd(dname+"-attr");
console.time(dname+"-data");
for(i=0;i<10000;i++){
dobj.data("data-test","a"+i);
}
console.timeEnd(dname+"-data");
}
function runlast(dobj,dname){
console.log("runlast "+dname);
console.time(dname+"-data");
for(i=0;i<10000;i++){
dobj.data("data-test","a"+i);
}
console.timeEnd(dname+"-data");
console.time(dname+"-attr");
for(i=0;i<10000;i++){
dobj.attr("data-test","a"+i);
}
console.timeEnd(dname+"-attr");
}
$().ready(function() {
runfirst($("#rp4"),"#rp4");
runfirst($("#rp3"),"#rp3");
runlast($("#rp2"),"#rp2");
runlast($("#rp1"),"#rp1");
});
</script>
</head>
<body>
<div id="rp1">Testdiv 1</div>
<div id="rp2" data-test="1">Testdiv 2</div>
<div id="rp3">Testdiv 3</div>
<div id="rp4" data-test="1">Testdiv 4</div>
</body>
</html>
It should also show if there is a difference with a predefined data-test
or not.
One result was this:
runfirst #rp4
#rp4-attr: 515ms
#rp4-data: 268ms
runfirst #rp3
#rp3-attr: 505ms
#rp3-data: 264ms
runlast #rp2
#rp2-data: 260ms
#rp2-attr: 521ms
runlast #rp1
#rp1-data: 284ms
#rp1-attr: 525ms
So the .attr()
function did always need more time than the .data()
function. This is an argument for .data()
I thought. Because performance is always an argument!
Then I wanted to post my results here with some questions, and in the act of writing I pared with the questions Stack Overflow showed me (similar titles)
And true enough, there was one interesting post about performance
I read it and run their example. And now I am confused! This test showed that .data()
is slower then .attr()
!?!! Why is that so?
First I thought it is because of a different jQuery library so I edited it and saved the new one. But the result wasn't changing...
So now my questions to you:
- Why are there some differences in the performance in these two examples?
- Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?
Now depending on the performance:
- Would performance be an argument for you using
.attr()
instead of data, if it shows that.attr()
is better? Although data is meant to be used for.data()
?
UPDATE 1:
I did see that without overhead .data()
is much faster. Misinterpreted the data :) But I'm more interested in my second question. :)
Would you prefer to use data- HTML5 attributes instead of data, if it represents a state? Although it wouldn't be needed at the time of coding? Why - Why not?
Are there some other reasons you can think of, to use .attr()
and not .data()
? e.g. interoperability? because .data()
is jquery style and HTML Attributes can be read by all...
UPDATE 2:
As we see from T.J Crowder's speed test in his answer attr
is much faster then data
! which is again confusing me :) But please! Performance is an argument, but not the highest! So give answers to my other questions please too!
UPDATE 3:
My test seems to be false because of the fire-bug I used while testing! The same file in chrome listed attr
faster and a second test on jsperf also says attr
is faster
- "Would performance be an argument for you using .attr() instead of data, if it shows that .attr() is better?" Yes... What else can be an argument?! – gdoron Commented Mar 20, 2012 at 8:47
- Others could be: Better adjustable, beutifuler code, better editable, better understandable, etc... e.g. OOP Programming has less performance than procedural, but it is often better :) – Neysor Commented Mar 20, 2012 at 8:50
-
4
"Because performance is always an argument!" Not in 2012. Let's look at your
runfirst #rp4
results: 10k iterations ofattr
took 515ms; 10k iterations ofdata
took 268ms. That's 51.5 usec (microseconds, millionths of a second) each vs. 26.8 usec each. So you're wondering whether to usedata
if it saves you 24.7 usec. Humans perceive things on the order of tenths of seconds. So for it to matter, you have to do this op roughly 4,000 times in a tight loop for a human to notice the difference. That's just not even close to worth worrying about, even in a mousemove handler. :-) – T.J. Crowder Commented Mar 20, 2012 at 8:51 - @T.J.Crowder i agree with you as you can see to the response of gdoron. I did mean that performance is an argument, but not always the highest :) – Neysor Commented Mar 20, 2012 at 8:56
- 1 @Neysor: Ah, quite! An argument. Good distinction. – T.J. Crowder Commented Mar 20, 2012 at 9:02
3 Answers
Reset to default 15This performance part of the question screams of premature optimization; see below. (Lest you get the wrong idea: I too am frequently guilty of wondering about the same sort of premature optimization question.)
But getting performance out of the way (other points addressed below the graph): As far as I can see, attr
is faster than data
in jQuery 1.7.1: http://jsperf./jquery-setting-attr-vs-data This surprises me. Not that it's remotely likely to matter.
Gratuitous bar graph (longer lines = faster performance):
Are there some other reasons you can think of, to use .attr() and not .data()?
At least a couple e to mind:
The advantage of
data
is that it doesn't have to write to the element every time; you only write to the actual element the first time, and from then on jQuery is just updating a value in a JavaScript object it maintains in a separate object cache (connected to the element via a key). (I'm not sure why it's slower thanattr
; perhaps because of the indirection.)One thing I dislike about
data
is that it's not symmetrical: The first time you accessdata
on an element, the data object is seeded withdata-*
attributes from the element; but from there on out, there is no connection between the two.Example (live copy | live source):
var target = $("#target"); display("data('foo'): " + target.data("foo")); display("data-foo: " + target.attr("data-foo")); display("Setting data('foo')"); target.data("foo", "updated data('foo')"); display("data('foo'): " + target.data("foo")); display("data-foo: " + target.attr("data-foo")); display("Setting data-foo"); target.attr("data-foo", "updated data-foo"); display("data('foo'): " + target.data("foo")); display("data-foo: " + target.attr("data-foo"));
Assuming the
#target
element starts out withdata-foo="bar"
, the output is:data('foo'): bar data-foo: bar Setting data('foo') data('foo'): updated data('foo') data-foo: bar Setting data-foo data('foo'): updated data('foo') data-foo: updated data-foo
That can be confusing and surprising. The way you have to think about it is that the
data-*
attributes are default values only. I just don't like how they're so dependent on whether you've calleddata
before or not; unless you never write to thedata-*
attribute directly, you can't be sure what valuedata
will get (the original from the markup, or a value you updated later before you calleddata
). It seems a bit chaotic to me, but if you set yourself rules (never write todata-*
attributes directly and only ever usedata
, for instance), you can avoid the chaos.When you use
attr
, you can only store strings. When you usedata
, you can store any JavaScript value or object reference.
Because performance is always an argument!
Not in 2012. :-) Or at least, it's a lot lower down the list relative to other arguments than it used to be absent a specific, demonstrable performance problem.
Let's look at your runfirst #rp4
results: 10k iterations of attr
took 515ms; 10k iterations of data
took 268ms. That's 51.5 usec (microseconds, millionths of a second) each vs. 26.8 usec each. So you're wondering whether to use data
if it saves you 24.7 usec per operation. Humans perceive things on the order of tenths of seconds. So for it to matter, you have to do this op roughly 4,000 times in a tight loop for a human to notice the difference. That's just not even close to worth worrying about, even in a mousemove
handler.
If you're into that kind of territory (4,000/second in a tight loop), you'll probably want to avoid storing the information on the element at all.
Given that .data()
is indeed slower than .attr()
on most browsers, but the speed difference is not important in this question, one advantage of data()
over attr()
is that data will automatically coerce data-
attributes to numbers
or to boolean
values if they match.
That means that
<div id="boolean" data-t="true" data-f="false">
will result in boolean runtime value of true
& false
when you run this:
console.log($('#boolean').data('t')); // reports true (not a string)
console.log($('#boolean').data('f')); // reports false (not a string)
and
<div id="number" data-n="123.456">
will result in a number runtime value of 123.456
when you run this:
console.log($('#number').data('n')); // Reports 123.456 (not a string)
attr
on the other hand only works with strings, but will convert value to strings for saving. It will not coerce values when you fetch them.
The choice between attr
and data
depends on the feature you need for a specific example:
- Where I inject
data-
settings from the server into pages, I tend to usedata()
to access them, if only because it is shorter code. - If I need the data to be visible in the DOM, I will use
attr()
to save the values`.
You may use jQuery.data. It's almost always the fastest. jQuery tries to optimize its function on every browsers, and maximize pability. So with new versions of jQuery, you may gain performance for this function.
This 2nd test gave me jQuery.data
as the winner.