What is happening behind .setAttribute vs .attribute=?
Description:
I am using simple javascript
to set a the value of an input
. I am using multiple methods that appear to be the same but with different results. Here is an example:
HTML:
<input name="testinput" value="" type="text" />
Javascript:
var input = document.getElementByTagName('input')[0];
input.value = "5"
console.log(input.value) // returns "5"
console.log(input.getAttribute("value")) // returns ""
Of course the functionality is reversed when using the setAttribute()
function. Yet, when on form submit they both give a input=5
result.
Question:
What is the point of separating the two properties? is the .value
stored differently than the .getAttribute("value")
?
Disclaimer:
I have read:
- When to use setAttribute vs .attribute= in JavaScript?
- Setting a property via property or setAttribute
Both of those question/answers left me confused and unsatisfied.
Solution 1:
input.value
is dot notation, it sets the value
property of the input object.
It does in no way update any attributes, so trying to get an attribute with the same name will not return the updated value.
If for some reason you have to update the attribute, you would do
input.setAttribute('value', 'new_value');
but you shouldn't have to use that, as you generally should be working with the properties, not the attributes, and you'd set and get the value
property, not the attribute.
An attribute in HTML is a key / value pair inside the opening and closing brackets, as in
<div attribute="attribute_value"></div>
In many cases such attributes will set the initial value of the underlying property, and the property is a named key with a value, that is attached to the internal model of an element, which is what we access with javascript, the object holding the model and data for the element.
Changing any of that objects keys or values does not change the HTML, only the internal representation of the element, the object. However, changing the HTML attributes will in some cases change the object representation of the element.
getAttribute
gets the actual attributes from the HTML, not the properties, while element.value
clearly accesses a named property in the object representing that element.
Solution 2:
It's important to take note of the differences between attributes and properties.
The value
attribute
The value
attribute of an <input>
, visible in the HTML representation of the element, is mapped to the defaultValue
property. For example:
var i = document.createElement('input');
i.setAttribute('value', 'foo');
console.log(i.defaultValue, i.getAttribute('value')); // "foo foo"
i.defaultValue = 'bar';
console.log(i.defaultValue, i.getAttribute('value')); // "bar bar"
The value
property
The value
property mirrors the defaultValue
property (and value
attribute) until it's explicitly been given a value, so:
var i = document.createElement('input');
i.defaultValue = 'foo';
console.log(i.value); // "foo"
i.value = 'bar';
i.defaultValue = 'foo';
console.log(i.value); // "bar"
This is another way of looking at it:
<input value="foo">
↑↓
input.defaultValue = "foo";
↓
input.value
get(): value === undefined ? input.defaultValue : value
set(newValue): value := newValue
Anchors
When using anchors, the href
attribute and href
property update each other, but in a different way, e.g.:
var a = document.createElement('a');
a.setAttribute('href', '/test');
console.log(a.href); // "http://stackoverflow.com/test"
a.href = '/test';
console.log(a.getAttribute('href')); // "/test"
Other elements
Here's a (partial) list of attributes and their corresponding properties:
element | attribute | property
---------+-----------+----------------
option | selected | defaultSelected (bool)
label | for | htmlFor
input | checked | defaultChecked (bool)
select | multiple | multiple (bool)
li | value | value (int)
As you can see, whereas the attributes are always strings, the corresponding properties may be of other types.