Retrieving HTML attribute values "the DOM 0 way"

Solution 1:

jQuery's attr() method is misleadingly named, badly documented and hides a very important distinction: the difference between attributes and properties, something which appears to be poorly understood by many web developers, particularly those whose introduction to JavaScript has come from jQuery.

If you read no further, just take this away: you will almost never need to use attributes. It's almost always better to use the corresponding property. Indeed, this is what jQuery's attr() method usually does used to do prior to version 1.6.

Reasons to use a property and avoid getAttribute() and setAttribute() when dealing with HTML DOMs:

  • IE's implementation is broken. In older versions and quirks modes of more recent versions, attributes map directly to properties, which is contrary to the DOM standard. One consequence of this is that event handler attributes (onclick etc.) are thoroughly broken in IE. Always use a property for an event handler. Another consequence of this is that IE in these modes and versions requires you to use getAttribute("className") instead of getAttribute("class") to retrieve the class attribute.
  • Properties are (mostly) consistently implemented cross-browser
  • The relationship between some properties and attributes is not as you might think. Some attributes, notably the value attribute of an <input> element, are not tied to the property with the same name: once the value of an input has been changed (either by the user or script), getting or setting the value attribute has no effect. Instead, the value attribute is synchronized with the defaultValue property.
  • Properties are usually more convenient. Think for example about boolean attributes such as checked: this is represented in the DOM as a boolean checked property while confusion reigns about how to set the checkedness of a checkbox using an attribute. Is it removeAttribute("checked")? setAttribute("checked", "")? setAttribute("checked", false)? All are wrong, because the checked attribute is actually mapped to the defaultChecked property.

There are some situations where using an attribute may be desirable. For example, the href property of an <a> element always reports a fully qualified URL while getAttribute("href") will return the string specified in the HTML href attribute verbatim. Except, of course, in IE. jQuery's attr() does attempt to normalize this kind of inconsistency.

Some more information on this subject: http://reference.sitepoint.com/javascript/Element/setAttribute, and also this from MSDN: http://msdn.microsoft.com/en-us/library/dd347148%28v=vs.85%29.aspx

Finally, I strongly recommend using the DOM properties directly wherever possible rather than using jQuery's attr() method, but there are special cases (such as href) it handles that you need to be aware of. Of the properties you mention, all of them are completely safe to use cross-browser, with the following exceptions:

  • foo.href and foo.src (which suffers from a similar problem) as mentioned above.
  • foo.type can only be set on an <input> element before it's been added to the DOM.
  • foo.selected (where foo is an <option> element) apparently has a bug in older versions of Safari, as noted in another answer.

Solution 2:

Looking at how jQuery handles it:

  • href, src, and style attributes need special treatment.
  • Safari has a bug when accessing "selected" attribute on a select element. If accessing the "selected" attribute, Safari needs special treatment.

Check out the jQuery source, and search for this line to see what I mean by "special treatment":
attr: function( elem, name, value, pass ) {

In short: I think it safe to do what you want for most of the attributes listed, except for those shown above.


To keep things easy, you could do this:

$foo = $("#foo");
console.log( $foo.attr("id"), $foo.attr("style"), $foo.attr("href") );
Only 1 jQuery object is made, and you don't have to worry about manually handling anything.