First and foremost:
This is not a bug in jQuery.
There is a significant difference between an element
attribute:
var attr = element.getAttribute('foo');
and an element property:
var prop = element.foo;
This answer lays it out very nicely — the short version is that attribute vs. property is messy, and browsers haven't always gotten it right, but you almost always want to use the property, not the attribute when working with the DOM.
Forget about attributes. You nearly always want a property, not an attribute. Where both a property and an attribute with the same name exists, the property always represents the current state while the attribute (in most browsers) represents the initial state. This affects properties such as the value property of <input>
elements.
If you now understand the attribute cluster!@#$, you should hopefully see where this is going.
The selector 'input[value=""]'
is an attribute selector. That means it's not a property selector. In both rounds in your example, $('input[value=""]')
matches only <input id="input2" value=""/>
, since that element (and only that element) is the one that:
- Has a
value
attribute, and
- That
value
attribute is equal to the empty string.
.val()
sets the <input>
element's value property, not the value attribute. The attribute selector matches, as the name implies, the element's attribute, so of course it's not going to select anything different if the attribute hasn't changed.
Additionally, jQuery does all sorts of fancy stuff under the hood which:
- Provides consistent behavior across browsers, and
- Provides behavior consistent with the documentation, and
- Especially with
.attr()
(which has quite the checkered past) can be really ugly.
Oh, and one last link: John Resig on jQuery 1.6 and .attr()
. Read it.