浏览器中的DOM
DOM in the Browser World
文本对象模型(DOM)是一个独立于语言的,用于操作XML和HTML文档的程序接口(API)。
在浏览器中主要用来与HTML打交道,同样也用在web程序中获取XML文档,并使用DOM API来访问文件中的数据。
DOM在浏览器中的接口是用js实现的。
天生就慢(Inherently Slow)
两个相互独立的功能只要通过接口彼此链接就会产生消耗。
而连接的次数越多则产生的消耗就越高。
DOM访问与修改(DOM Access and Modification)
访问DOM是有代价的,而修改元素的消耗更高,因为它会导致浏览器重新计算页面的几何变化。
减少访问DOM的次数,把运算尽量留在ECMAscript这一段处理。
innerHTML 对比DOM方法(innerHTML Versus DOM Methods)
innerHTML属性与document.createElement()的原生DOM方法两者的性能相差无几。
但是除开最新版的WebKit内核(Chorme和Safari)之外的所有浏览器中,innerHTML会更快一些。
应该根据可读性,稳定性,团队习惯,代码风格来综合决定使用哪种方式
节点克隆(Cloning Nodes)
克隆已有元素——使用element.cloneNode()(element表示已有节点)来替代document.createElement()。
在大多数浏览器中克隆节点更有效率一丢丢。
HTML集合 (HTML Collections)
HTML 集合是包含了DOM节点引用的类数组对象。以下方法的返回值就是一个集合:
- document.getElementByName();
- document.getElementByClassName();
- document.getElementByTagName();
下面的属性同样是返回HTML集合:
- document.images(所有的img元素)
- document.links(所有的a元素)
- document.forms(所有表单元素)
- document.foms[0].elements(页面中第一个表单的所有字段)
这些返回的值只是类似数组并没有push()、slice()等方法。但提供了一个类似数组中的length属性,并且还能以数字索引的方式访问列表中的元素。
HTML集合一直与文档保持着链接,每次需要最新信息的时候都会重复执行查询过程,哪怕只是获取集合里的元素个数,这正是低效之源。
昂贵的集合
var alldivs = document.getElementsByTagName('div');
for(var i = 0 ;i<alldivs.length;i++){
document.body.appendChild(document.createElement('div'));
}
像这样遍历HTML集合可能会导致逻辑错误,而且也很慢,因为每次迭代都执行查询操作。
读取一个集合的length的速度比读取普通数组的length要慢很多。
比较好的方法是将length赋值给一个新的变量,这样就减少了执行时间。HTML集合亦可以通过toArray()转成数组。
访问集合元素时使用局部变量
需要多次访问同一个DOM属性或方法需要多次访问时,最好使用一个局部变量缓存此成员。
当遍历一个集合石,第一优化原则是把集合存储在局部变量中,并把length缓存在循环外部,然后,使用局部变量替代这些需要多次读取的元素。
较慢:
function collectionGlobal(){
var coll = document.getElementsByTagName('div'),
len = coll.length,
name = '';
for(var count = 0 ; count < len ; count++){
name = document.getElementsByTagName('div')[count].nodeName;
name = document.getElementsByTagName('div')[count].nodeType;
name = document.getElementsByTagName('div')[count].tagName;
}
return name;
}
较快:
function collectionGlobal(){
var coll = document.getElementsByTagName('div'),
len = coll.length,
name = '';
for(var count = 0 ; count < len ; count++){
name = coll[count].nodeName;
name = coll[count].nodeType;
name = coll[count].tagName;
}
return name;
}
最快:
function collectionGlobal(){
var coll = document.getElementsByTagName('div'),
len = coll.length,
name = '',
el = null;
for(var count = 0 ; count < len ; count++){
el = coll[count];
name = el.nodeName;
name = el.nodeType;
name = el.tagName;
}
return name;
}