DOM 属性(Properties 写在对象内的)
DOM 节点是常规的 JavaScript 对象。
例如,在 document.body 中创建一个新的属性:
document.body.myData = {
name: 'Caesar',
title: 'Imperator'
};
document.body.sayTagName = function() {
alert(this.tagName);
};
Element.prototype.sayHi = function() {
alert(`Hello, I'm ${this.tagName}`);
};
alert(document.body.myData.title); // Imperator
document.documentElement.sayHi(); // Hello, I'm HTML
document.body.sayHi(); // Hello, I'm BODY
document.body.sayTagName(); // BODY(这个方法中的 "this" 的值是 document.body)
所以,DOM 属性和方法的行为就像常规的 Javascript 对象一样,并且大小写敏感。
HTML 特性(Attributes 写在 HTML 上的)
在 HTML 中,标签可能拥有特性(attributes)。当浏览器解析 HTML 文本,并根据标签创建 DOM 对象时,浏览器会辨别 标准的 特性并以此创建 DOM 属性。
所以,当一个元素有 id 或其他 标准的 特性,那么就会生成对应的 DOM 属性。但是非 标准的 特性则不会。
<body id="test" something="non-standard">
<script>
alert(document.body.id); // test
// 非标准的特性没有获得对应的属性
alert(document.body.something); // undefined
</script>
</body>
但是某些标准的特性只有在特点标签上有,例如
<body id="body" type="...">
<input id="input" type="text">
<script>
alert(input.type); // text
alert(body.type); // undefined
</script>
</body>
如何访问一个非标准的特性?
document.body.hasAttribute('something')
—— 检查特性是否存在。document.body.getAttribute('something')
—— 获取这个特性值。document.body.setAttribute('something', 'value')
—— 设置这个特性值。document.body.removeAttribute('something')
—— 删除这个特性。document.body.attributes
—— 获取所有特性。
HTML 特性有以下几个特征
- 大小写不敏感
- 类型永远是字符串
<body>
<div id="elem" about="Elephant"></div>
<script>
alert( elem.getAttribute('About') ); // (1) 'Elephant',读取
elem.setAttribute('Test', 123); // (2) 写入
alert( elem.outerHTML ); // (3) 查看特性是否在 HTML 中(在)
for (let attr of elem.attributes) { // (4) 列出所有
alert( `${attr.name} = ${attr.value}` );
}
</script>
</body>
属性-特性同步
当一个标准的特性被改变,对应的属性也会自动更新,(除了几个特例)反之亦然。 在下面这个示例中,id 被修改为特性,我们可以看到对应的属性也发生了变化。然后反过来也是同样的效果:
<input>
<script>
let input = document.querySelector('input');
// 特性 => 属性
input.setAttribute('id', 'id');
alert(input.id); // id(被更新了)
// 属性 => 特性
input.id = 'newId';
alert(input.getAttribute('id')); // newId(被更新了)
</script>
特例
有一些特例,特性和属性之间的同步并不发生。 例如 input 元素的 value 只能 特性 => 属性,而不能反过来。
<input>
<script>
let input = document.querySelector('input');
// 特性 => 属性
input.setAttribute('value', 'text');
alert(input.value); // text
// 这个操作无效,属性 => 特性
input.value = 'newValue';
alert(input.getAttribute('value')); // text(没有被更新!)
</script>
DOM 属性类型不固定
DOM 属性的类型可以是任意的 JavaScript 类型。
DOM 属性不总是字符串类型的。例如,input.checked
属性(对于 checkbox
的)是布尔型的。
<input id="input" type="checkbox" checked> checkbox
<script>
alert(input.getAttribute('checked')); // 特性值是:空字符串
alert(input.checked); // 属性值是:true
</script>
style 特性是字符串类型的,但 style 属性是一个对象
<div id="div" style="color:red;font-size:120%">Hello</div>
<script>
// 字符串
alert(div.getAttribute('style')); // color:red;font-size:120%
// 对象
alert(div.style); // [object CSSStyleDeclaration]
alert(div.style.color); // red
</script>
特例
有的 DOM 属性即使和特性的类型是相同的,但它们的值可能不同。
例如,href
DOM 属性一直是一个 完整的 URL,即使该特性包含一个相对路径或者包含一个 #hash。
<a id="a" href="#hello">link</a>
<script>
// 特性
alert(a.getAttribute('href')); // #hello
// 属性
alert(a.href); // http://site.com/page#hello 形式的完整 URL
</script>
非标准的特性,dataset
如果我们想用非标准的特性来存储数据,我们可以使用 data-*
特性。
这些特性会被自动转换为 DOM 属性。
<div id="elem" data-about="Elephant" data-test="123"></div>
<script>
let elem = document.getElementById('elem');
// 特性 => 属性
alert(elem.dataset.about); // Elephant
alert(elem.dataset.test); // 123
</script>
总结
- 特性(attribute)—— 写在 HTML 中的内容。
- 属性(property)—— 写在 JavaScript 对象中的内容。
对比
不同点 | 特性(attribute) | 属性(property) |
---|---|---|
访问方式 | 通过 getAttribute/setAttribute 访问 | 直接通过点语法访问 |
大小写敏感程度 | 大小写不敏感 | 大小写敏感 |
类型 | 类型始终是字符串 | 类型可以是任意 JavaScript 类型 |
操作特性(attribute)的方法
hasAttribute(name)
—— 检查特性是否存在。getAttribute(name)
—— 获取特性值。setAttribute(name, value)
—— 设置特性值。removeAttribute(name)
—— 删除特性。attributes
—— 获取所有特性的集合。
在大多数情况下,最好使用 DOM 属性。仅当 DOM 属性无法满足开发需求,并且我们真的需要特性时,才使用特性,例如:
- 我们需要一个非标准的特性。但是如果它以 data- 开头,那么我们应该使用 dataset。
- 我们想要读取 HTML 中“所写的”值。对应的 DOM 属性可能不同,例如 href 属性一直是一个 完整的 URL,但是我们想要的是“原始的”值。