JavaScript特性(attribute)、属性(property)和样式(style)

简介: 最近在研读一本巨著《JavaScript忍者秘籍》,里面有一篇文章提到了这3个概念。书中的源码可以在此下载。我将源码放到了线上,如果不想下载,可以直接访问在线网址,修改页面名就能访问到相应示例代码。

最近在研读一本巨著《JavaScript忍者秘籍》,里面有一篇文章提到了这3个概念。

书中的源码可以在此下载。我将源码放到了线上,如果不想下载,可以直接访问在线网址,修改页面名就能访问到相应示例代码。


2.png


一、DOM特性和DOM属性


attribute(特性),是我们赋予某个事物的特质或对象,attribute是HTML标签上的特性,它的值只能够是字符串

property(属性),是早已存在的不需要外界赋予的特质,property是DOM中的属性,是JavaScript里的对象

在访问元素特性值时有两种方式:

1. 传统DOM方法getAttributesetAttribute

2. 使用DOM对象上与之对应的属性

例如通过两种方式获取id的值:


e.getAttribute('id');
e.id;


3.png


1)跨浏览器命名

特性和属性命名之间的差异会更多。

在大多数浏览器中可以用class获取到class特性,但IE却要使用className。

2)命名限制

特性表示为传递给DOM方法的字符串,其命名规范是非常自由的。

而属性名称,由于可以作为标识符使用点表示法进行访问,所以其命名规范更受限制。


4.png


3)HTML和XML之间的差异

在处理一个XML DOM的时候,不会在元素上自动创建属性值来表示特性值。

因此,我们需要使用传统的DOM特性方法获取特性的值。

elem.ownerDocument只读属性会返回当前节点的顶层的 document 对象。


function isXML(elem) {
  return (elem.ownerDocument || elem.documentElement).nodeName.toLowerCase() !== 'html';
}


4)自定义特性的行为

要想访问自定义特性值,需要使用DOM方法getAttribute()与setAttribute()。

在HTML5中,对所有的自定义特性使用“data-”前缀。

5)性能注意事项

总的来说,属性的访问速度比相应DOM特性方法的访问速度要快,特别是在IE浏览器中。

下面做个测试,分别用两种方式读取和设置500W次。可以在不同浏览器中点开这个地址来查看测试结构。

下面的截图是在Chrome中的结果:


6.png


二、跨浏览器的Attribute问题


1)DOM中的id/name膨胀

5大浏览器都会将表单input元素的id和name特性作为<form>元素的属性值进行引用。

产生的这些属性,会主动覆盖form元素上已经存在的同名属性。

此外,IE浏览器不仅会替换属性值,甚至还会替换该属性值上的特性值。


<form id="testForm" action="/">                       
      <input type="text" id="id"/>
      <input type="text" name="action"/>
</form>
var form = document.getElementById('testForm');
assert(form.id === 'testForm', "the id property is untouched");
assert(form.action === '/', "the action property is untouched");
assert(form.getAttribute('id') === 'testForm',  "the id attribute is untouched");
assert(form.getAttribute('action') === '/', "the action attribute is untouched");


7.png


在所有的现代浏览器中,由于这些input定义的id和name的值,表单的id和action属性都会被input元素的引用所替代。

解决方法是获取描述元素特性本身的原始DOM节点,该节点没有被浏览器修改:


var action = element.getAttributeNode('action').nodeValue;


2)URL规范化

在访问一个引用了URL属性时(例如src、href或action),该URL值会自动将原始值转换成完整规范的URL。


<a href="listing-11.5.html" id="testSubject">Self</a>


var link = document.getElementById('testSubject');
var linkHref = link.getAttributeNode('href').nodeValue; //#1
assert(linkHref === 'listing-11.5.html',  'link node value is ok');
assert(link.href === 'listing-11.5.html',  'link property value is ok');
assert(link.getAttribute('href') == linkHref, 'link attribute not modified');


8.png

3)style特性

HTML DOM元素有一个style属性,通过该属性我们能获取元素的样式信息,例如element.style.color。


<span style="color:red"></span>


如果要获取“color:red”字符串,那么style属性没用,得用getAttribute('style')方法获取。

但IE中得用element.style.cssText获取。

4)节点名称

在HTML文档中,nodeName属性返回的名称将是大写(例如HTML、BODY)。

在XML或XHTML文档中,nodeName返回的名称是用户指定的名称,可以大写、小写或混合。

 

三、令人头疼的样式特性


1)样式在何处


<style>
      div { font-size: 1.8em; border: 0 solid gold; }
</style>
<div style="color:#000;" title="Ninja power!">
      忍者
</div>


var div = document.getElementsByTagName("div")[0];
assert(div.style.color == 'rgb(0, 0, 0)' ||  div.style.color == '#000','color was recorded');
assert(div.style.fontSize == '1.8em', 'fontSize was recorded');
assert(div.style.borderWidth == '0', 'borderWidth was recorded');
div.style.borderWidth = "4px";                    //#6
assert(div.style.borderWidth == '4px', 'borderWidth was replaced');

1. 大多数颜色都会转换成RGB颜色符号,有一些会转换为颜色的名称。

2. font-size和border都被记录在了style标签内,样式是继承获取的,但div.style属性中没有获取到。

3. 一个元素的style属性中的任何一个样式的优先级都要高于样式表所继承的样式(即便使用了“!important”注解规则)。


2)样式属性命名


CSS特性将多余一个单词的用连字符分隔,例如font-size、font-weight等。

在JS中可以用带有连字符的样式名称,但不能使用点运算符来访问样式了。


var size = element.style['font-size'];//允许
var size = element.style.font-size;//不允许
var size = element.style.fontSize;//允许


在JS中多个单词的CSS样式名称用驼峰的方式命名,例如fontSize、fontWeight。

具体的CSS样式表对应属性可以参考《CSS Properties Reference


3)设置多个样式属性


不能通过直接给style属性设置字符串(如:elt.style = "color: blue;")来设置style,因为style应被当成是只读的。

设置多个属性可以用cssText或setAttribute,其中cssText会将重复属性覆盖屌。


elt.style.cssText = "color: blue"; // 设置多个样式属性 当带前缀的时候-webkit-transform:rotate(0deg),会过滤掉-webkit,只能用下面的方式
elt.setAttribute("style", "color: blue"); // 设置多个样式属性 


4)float样式属性

float是JS中的保留关键字,浏览器需要提供另外一个替代名称。

大部分浏览器使用cssFloat,但IE使用styleFloat。


5)像素值的转换过程

为style属性设置数字时,必须要指定单位,以便在所有的浏览器上都能使用。


element.style.height = '10px';//安全
element.style.height = 10;//不安全

6)测量元素的高度和宽度

offsetHeight和offsetWidth可以获取元素的高度和宽度,不过这两个属性值包括了padding值,更多元素尺寸属性可以参考《JavaScript中尺寸、坐标

但如果元素隐藏(例如display:none),获取到的数值都是0。对于隐藏元素可以用如下的方法:



9.png

可以查看在线demo实例


10.png

11.png


“Pole”是显示的图片,就是那个忍者。

而“Shuriken”是隐藏的图片,一开始是获取不到宽度的,在使用了上面的技巧后就能获取到了。


7)通过opacity看透明度

所有现代浏览器,包括IE9支持opacity属性,但IE9之前的版本需要使用专用的alpha过滤法。


opacity: .5;
filter: alpha(opacity=50)


支持opacity的浏览器,总会将值规范为小于1.0且以0开头的值。

例如“opacity:.5”,那么支持的将返回“0.5”,不支持的将返回“.5”。

通过特性仿真,可以判断浏览器是否支持opacity。


//特性仿真检测
var div = document.createElement("div");                 //#1
div. setAttribute('style','opacity:.5');
var OPACITY_SUPPORTED = div.style.opacity === "0.5";
assert(OPACITY_SUPPORTED,   "Opacity is supported.");


8)颜色属性


通过不同的计算样式方法访问这些颜色值的时候,各种浏览器的返回值几乎都不一致。

12.png

下面是一个在线demo,在不同浏览器中展示的颜色值:

IE8

Firefox Chrome

13.png

14.png

15.png

IE8不支持RGBA和HSL格式

Firefox不仅保留了颜色名称,

而且标准颜色是RGB和RGBA格式

Webkit浏览器(Chrome、Safari)

标准颜色是RGB和RGBA格式



四、获取计算样式


1)window.getComputedStyle()与element.currentStyle

一个元素的计算样式(computed style)都是应用在该元素上的所有样式组合。

这些样式包括样式表、元素的style特性,以及脚本对style属性的各种操作。

现代浏览器(包括IE9)的实现方法为:window.getComputedStyle(),返回接口提供了一个getPropertyValue()的方法。

IE9之前的版本,通过附加到所有元素上的currentStyle属性,表现和style属性一样。


/**
* property可以传入驼峰或分隔符方式
*/
function fetchComputedStyle(element, property) { //#3
  //现代浏览器 包括IE9
  if (window.getComputedStyle) {
    var computedStyles = window.getComputedStyle(element); //#4
    if (computedStyles) { //#5
      property = property.replace(/([A-Z])/g, '-$1').toLowerCase();
      return computedStyles.getPropertyValue(property);//getPropertyValue中需要传入分隔符字符串,例如font-size
    }
  } else if (element.currentStyle) { //IE9以下
    property = property.replace(
      /-([a-z])/ig,
      function(all, letter) {
        return letter.toUpperCase();
      });
    return element.currentStyle[property];
  }
}



相关文章
|
23天前
|
监控 JavaScript 前端开发
确定使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript
【10月更文挑战第24天】选择使用 `defer` 属性还是 `async` 属性来异步加载 JavaScript 是一个需要综合考虑多个因素的决策。需要根据脚本之间的依赖关系、页面加载性能要求、脚本的功能和重要性等因素来进行权衡。在实际应用中,需要通过测试和验证来确定最适合的加载方式,以提供更好的用户体验和页面性能。
|
23天前
|
监控 JavaScript 前端开发
使用 `defer` 属性异步加载 JavaScript
【10月更文挑战第24天】使用 `defer` 属性异步加载 JavaScript 是一种有效的提高页面性能和用户体验的方法。通过合理设置 `defer` 属性,可以在不影响页面渲染的情况下异步加载脚本,并确保脚本的执行顺序。在实际应用中,需要根据具体情况选择合适的加载方式,并注意处理可能出现的问题,以确保页面能够正常加载和执行。
|
1月前
|
JavaScript 前端开发 编译器
掌握现代化JavaScript:ECMAScript提案与特性
【10月更文挑战第13天】本文介绍了ECMAScript(ES)的最新提案与特性,包括可选链、空值合并运算符、类字段和顶层Await等。通过跟踪TC39提案、使用Babel或TypeScript、测试兼容性以及逐步迁移,开发者可以高效地采用这些新特性,简化代码、提高开发效率并增强应用功能。文章还提供了实战技巧,帮助开发者在现代Web开发中充分利用这些现代化的特性。
|
1月前
|
JavaScript 前端开发 索引
JavaScript ES6及后续版本:新增的常用特性与亮点解析
JavaScript ES6及后续版本:新增的常用特性与亮点解析
32 4
|
1月前
|
移动开发 JavaScript 前端开发
原生js如何获取dom元素的自定义属性
原生js如何获取dom元素的自定义属性
53 4
|
20天前
|
前端开发 JavaScript
JavaScript新纪元:ES6+特性深度解析与实战应用
【10月更文挑战第29天】本文深入解析ES6+的核心特性,包括箭头函数、模板字符串、解构赋值、Promise、模块化和类等,结合实战应用,展示如何利用这些新特性编写更加高效和优雅的代码。
39 0
|
1月前
|
缓存 JavaScript 前端开发
探索Vue.js中的计算属性与侦听器
【10月更文挑战第5天】探索Vue.js中的计算属性与侦听器
23 1
|
2月前
|
JavaScript 前端开发 Oracle
软件工程师,学习下JavaScript ES6新特性吧
软件工程师,学习下JavaScript ES6新特性吧
43 9
|
1月前
|
移动开发 前端开发 JavaScript
JavaScript 中的样式切换方法
JavaScript 中的样式切换方法
15 0
|
1月前
|
存储 JavaScript 前端开发
js中map属性
js中map属性
19 0