HTML attributes vs DOM properties
1. 设置attributes可以映射到HTML上,但properties不会
const div = document.createElement('div');
div.setAttribute('foo', 'bar');
div.hello = 'world';
console.log(div.outerHTML); // '<div foo="bar"></div>'
2. attributes值的类型是string,但properties可以是任何类型
const div = document.createElement('div');
const obj = { foo: 'bar' };
div.setAttribute('foo', obj);
console.log(typeof div.getAttribute('foo')); // 'string'
console.log(div.getAttribute('foo')); // '[object Object]'
div.hello = obj;
console.log(typeof div.hello); // 'object'
console.log(div.hello); // { foo: 'bar' }
3. attributes名称大小写不敏感,但properties名称大小写敏感
<div id="test" HeLlO="world"></div>
<script>
const div = document.querySelector('#test');
console.log(div.getAttributeNames()); // ['id', 'hello']
div.setAttribute('FOO', 'bar');
console.log(div.getAttributeNames()); // ['id', 'hello', 'foo']
div.TeSt = 'value';
console.log(div.TeSt); // 'value'
console.log(div.test); // undefined
</script>
特殊情况
* Reflection
一些attributes的改变,会影响properties同步变化,如id,因为Element 有一个 id getter 和 setter,可以 Reflect id 属性。
当property映射attribute,attribute就是数据源,当你更新property,同时也是在更新attribute,当你读取property,也就是在读取attribute。
为了方便起见,大多数规范都会为每个已定义的attribute创建一个对应的property。在文章开头的例子中,由于 foo 不是规范定义的attribute,所以没有一个规范定义的 foo property来映射它。
一般情况,attribute和property映射名称是相同的,但是也有例外,如:
- 在
<img>
元素中,el.crossOrigin
property映射的是crossorigin
attribute - 在
label
元素中,el.htmlFor
property映射的是for
attribute - 在
<input>
元素中,defaultValue
property映射的是value
attribute - 在所有元素中,
el.ariaLabel
property映射的是aria-label
attribute - 在所有元素中,
el.className
property映射的是class
attribute
* Properties 带有验证和默认值,而Attributes则没有
在下面的例子中,验证由type getter处理。setter允许使用无效值 "foo",但当getter看到无效值或没有值时,就会返回 "text"。
const input = document.createElement('input');
console.log(input.getAttribute('type')); // null
console.log(input.type); // 'text'
input.type = 'number';
console.log(input.getAttribute('type')); // 'number'
console.log(input.type); // 'number'
input.type = 'foo';
console.log(input.getAttribute('type')); // 'foo'
console.log(input.type); // 'text'