As far as I can tell this might just be false. If you go to github.com (a random site which happens to include query 1.7.1 -- the latest version), open the console in either firebug or webkit inspector, and run the author's example:
var foo = $("body");
foo.data("mykey", "1.410");
foo.data("mykey");
...you get your original "1.410", not 1.41 as the author reports.
Secondly, he says there are "several bug reports on the jQuery website, where people are also confused by this behavior and all of them get closed with a wontfix" but links to none of them. Linking to them should be trivial and they'd help his case (or at least make it easy for me to figure out why he sees a bug and I don't). I searched and couldn't find any.
Finally, you shouldn't use .attr() to store arbitrary data as he recommends. Hanging javascript data off of DOM nodes will cause serious memory leaks if you're not careful. That's the reason .data() exists in the first place. See the "Cicular References" section of Understanding and Solving Internet Explorer Leak Patterns: http://msdn.microsoft.com/en-us/library/Bb250448
Yep, latchkey, I think you might want to rethink the article. As others have pointed out, you're seeing JavaScript's behaviour, not jQuery's. And this:
elem.data('foo', { 'a':1, 'b':2 });
elem.data('foo'); // Returns the object
Then what's the problem? You stored float 1.410 and got back float 1.41. They're equal. That's not jQuery, it's javascript: http://jsfiddle.net/kgp2H/1/
Edit, after the parent was edited to include the data attribute example:
You should update your post to clarify that you're talking about data attributes. That's a significant detail and shouldn't have been left out.
Now that you've clarified, jQuery does behave as you've stated, but it's not a bug. I can see how it could be unexpected behavior to some, but it's explicitly stated in the .data() documentation:
Every attempt is made to convert the string to a
JavaScript value (this includes booleans, numbers,
objects, arrays, and null) otherwise it is left as a
string. To retrieve the value's attribute as a string
without any attempt to convert it, use the attr() method.
That may be the documented behavior, but that doesn't make it the correct behavior. The problem is that we have a typeless language applying arbitrary type detection to strings... and it will invariably guess wrong.
A string of "1.410" is not the same as a float of 1.41. Running "1.410" full-circle through data() corrupts the input string. When you have data that has been entered by a user, you can't guarantee that it's not something that will happen to autoconvert.
This behavior is totally broken and should never be used. It will work 99.95% of the time, then fail in bizarre ways when a user types in something magic. These are the worst bugs in the world to hunt down. This really shouldn't be in jquery.
But 1.410 isn't a string, it's a float. What do you expect jQuery to do, parse the source of its caller and determine that you wrote 1.410 rather than 1.41? That's the only thing it could reasonably do, because the value it actually receives as an argument is identical in both cases.
Your example isn't very clear. http://jsfiddle.net/4bd23/1/ shows that data read from the HTML attribute may be coerced into a number, while data values set from JavaScript are always returned as the same type.
I can see why they would do this. Having to parseInt all default values wouldn't be very jQuery-like.
I wasn't aware of this. This looks like a bad design choice indeed. I hate when libraries convert stuff implicitly for you. html5's localStorage has a similar problem. Only, it converts whatever you are trying to store into a string. Would be better if it accepted only strings and threw an error if you tried to store something else, imho.
In what way does the author think this behaviour is wrong?
1.410 === 1.41
If he wanted to store a string, then he should actually store a string. .data() is just a thin wrapper around getting and setting values on an object, which initialises its initial values from the data-* attributes on the element in question (which should always be strings).
The problem is that the way it works is not actually useful. When I have user input data of 1.400, I need this string preserved as 1.400. I can't have jQuery mangling the data just because (to it) the string happens to look like a float.
The thing is removeData is pretty much useless because it only removes data from the jQuery cache, but if the data is missing from the cache jQuery will look in the DOM anyway.
19 comments
[ 2.7 ms ] story [ 50.6 ms ] threadSecondly, he says there are "several bug reports on the jQuery website, where people are also confused by this behavior and all of them get closed with a wontfix" but links to none of them. Linking to them should be trivial and they'd help his case (or at least make it easy for me to figure out why he sees a bug and I don't). I searched and couldn't find any.
Finally, you shouldn't use .attr() to store arbitrary data as he recommends. Hanging javascript data off of DOM nodes will cause serious memory leaks if you're not careful. That's the reason .data() exists in the first place. See the "Cicular References" section of Understanding and Solving Internet Explorer Leak Patterns: http://msdn.microsoft.com/en-us/library/Bb250448
http://jsfiddle.net/kgp2H/
Think of it this way, say you have a template that is putting some data into an element like this:
<button id="fooButton" data-key="1.400">Click me to edit something</button>
Now, using .data() to select the information out, will always return 1.4 instead of what you want, which is 1.400.
1.410 === 1.41
Edit, after the parent was edited to include the data attribute example:
You should update your post to clarify that you're talking about data attributes. That's a significant detail and shouldn't have been left out.
Now that you've clarified, jQuery does behave as you've stated, but it's not a bug. I can see how it could be unexpected behavior to some, but it's explicitly stated in the .data() documentation:
http://api.jquery.com/data/#data2A string of "1.410" is not the same as a float of 1.41. Running "1.410" full-circle through data() corrupts the input string. When you have data that has been entered by a user, you can't guarantee that it's not something that will happen to autoconvert.
This behavior is totally broken and should never be used. It will work 99.95% of the time, then fail in bizarre ways when a user types in something magic. These are the worst bugs in the world to hunt down. This really shouldn't be in jquery.
I can see why they would do this. Having to parseInt all default values wouldn't be very jQuery-like.
localStorage['a'] = {a:1}; localStorage['a'] -> "[object Object]"
Crap.
I don't understand the issue. He is putting in 1.410 and gets 1.41? Isn't that the expected result?
If he wanted to store a string, then he should actually store a string. .data() is just a thin wrapper around getting and setting values on an object, which initialises its initial values from the data-* attributes on the element in question (which should always be strings).
http://jsfiddle.net/KwjvA/
The root issue here is that the developer assumed how somethig worked, and didnt bother to learn how it actually worked.
I actually do have issues with data attribute for this exact reason, but that is no excuse for not looking up how it actually works.