Attributes and Properties



After getting into topics about JavaScript in browsers, two terminologies - attribute and property - appears alternatively. I still haven't made these two terminologies and concepts straight.

In fact, before getting into topics about JavaScript in browsers, I always use the terminology "property" to indicate a name and value owned by a JavaScript object. For example:
var obj = {
    x: 10,
    y: 20
};
I say that the object obj has properties x and y; the value of the property x is 10 and the value of y is 20.

Attributes represent the values that are defined on the markup of HTML tags. For example:
<input name="user" value="guest">
I say that the input tag has attributes name and value; their respective values are "user" and "guest".

Browsers parse the HTML document and create corresponding DOM elements for all tag. After parsing, DOM elements create all respective properties for all HTML attributes - whether written statically in the document or not. Basically, attributes and properties have the same name; if a tag defines an attribute value, its corresponding property will have that value. If a tag doesn't define some attributes, the corresponding DOM element provides properties default values.

In the above example, on the corresponding DOM elements of the input tag, the respective values for properties name and value are 'user' and 'guest'. You can get them as follows (assuming it's the first input tag of the document):
var input = document.getElementsByName('user')[0];
var name = input.name;
var value = input.value;

Now, properties name and value of the DOM element can be also called as attributes. In other words, the terminology attributes represents attributes of HTML tags; it also represents corresponding properties of DOM elements. If a tag doesn't define some attributes, the DOM element still has corresponding properties (attributes) and provides default values. For example, the above input tag doesn't define a type attribute, yet the corresponding property (attribute) of the DOM element has the value 'text'.

However, a HTML attribute and the corresponding DOM property don't always have an identical name. The class attribute is an example; it's a reserved word of JavaScript, so use the property className instead to get its value. Since for is a keyword, use the property htmlFor to return the for value of the label tag. For example:
<img id="logo" src="images/caterpillar.jpg"
     class="logo" title="Caterpillar's Logo" />

Getting the class value of the above tag may be as follow:
var className = document.getElementById('logo').className;
What you get from a property isn't always the same as the statically-written value of the corresponding attribute. For example, the src property of the img element is an absolute URL, even the corresponding attribute is a relative URL.

After a browser completes HTML parsing, it creates an attributes property - contains all written attributes of each tag - on each DOM element. The type of elements contained in attributes is Attr. You could show them by the following code:
var attributes = document.getElementById('logo').attributes;
for (var i = 0; i <attributes.length; i++) {
    var attrName = attributes [i]. nodeName;
    var attrValue = attributes [i
]. nodeValue;
    ...
}

If we simply use an object literal to represent the structure of a DOM element:
{
    attributes : {
        '0' : {nodeName : 'id', nodeValue : 'logo', ...},
        '1' : {nodeName : 'src', nodeValue : 'images/src', ...},
        '2' : {nodeName : 'class', nodeValue : 'logo', ...},
        '3' : {nodeName : 'title', nodeValue : 'Caterpillar\\’s logo', ...},
        length : 4
        ...
    },
    id : 'logo',
    src : 'http://caterpillar.onlyfun.net/images/caterpillar.jpg',
    className : 'logo',
    title : 'Caterpillar\'s logo',
    …
}

Properties of each Attr instance represents real attribute names and values of the corresponding tag. After parsing a document, attributes (properties) of DOM elements will correspond with properties of Attr instances contained in attributes.

Note that the above object literal is only used to illustrate the structure; it doesn't mean anything about real types of properties. The type of attributes is NamedNodeMap and each index stores an Attr instance. (A JavaScript Debugger is convenient for you to observe that.)

The getAttribute function of DOM elements returns an attribute of attributes; setAttribute are used to set it (will change the corresponding property simultaneously); removeAttribute is for removing.

Removing an attribute means removing the corresponding Attr instance of attributes, not the corresponding property (attribute) of the DOM element. The later will be set a default value after removeAttribute completes. If the tag doesn't define the attribute statically, getAttribute returns null. This doesn't mean the DOM element is lack of corresponding property, yet the corresponding property has a default value. Using setAttribute to set an attribute of attributes will changes the corresponding property of the DOM element simultaneously.

For example, the following code only removes the corresponding Attr instance of the src attribute. It doesn't remove the src property (attribute) of the DOM element. The src property just goes back to a default value '' - an empty string.
var img = document.getElementById('logo');
img.removeAttribute('src');
// the value of img.src is '', not undefined
// img.attributes['src'] is undefined
Changing properties (attributes) of a DOM element also affects attributes, and vice versa. But, there're exceptions. For example: 
<input id="user" value="guest">
Observe the following code:
document.getElementById('user').value = 'Justin';
var user1 = document.getElementById('user').value; // value is 'Justin'
var user2 = document.getElementById('user').getAttribute('value'); // value is 'guest'
You may use setAttribute to change attributes. For example:
document.getElementById('user').setAttribute('value', 'Justin');
var user1 = document.getElementById('user').value; // value is 'Justin'
var user2 = document.getElementById('user').getAttribute('value'); // value is 'Justin'