JavaScript 高效运行代码分析(5)

第二种方法是为元素定义新样式,而不是一个个赋值。这主要用于动态修改,如在动画中,无法事前知道新样式值。通过使用 style 对象的 cssText 属性,或者通过 setAttribute. 可以实现此技巧。Internet Explorer 不允许第二种形式,支持第一种形式。有些较老的浏览器,包括 Opera 8 需要使用第二种形式,不支持第一种形式。最简单的方式是测试看是否支持第一种形式,如果支持就使用,如果不支持则使用第二种形式。

复制代码 代码如下:

var posElem = document.getElementById('animation'); var newStyle = 'background: ' + newBack + ';' + 'color: ' + newColor + ';' + 'border: ' + newBorder + ';'; if( typeof( posElem.style.cssText ) != 'undefined' ) { posElem.style.cssText = newStyle; } else { posElem.setAttribute('style',newStyle); }

用流畅性换取速度

作为开发者,当然想要动画运行的越流畅越好,通常使用较小的时间间隔或较小的变化。如每10ms更新一次动画,或者每次移动1个像素。此动画可能在桌面电脑上或某些浏览器中可以完美运行。但10ms时间间隔可能是浏览器使用100%CPU才能达到的最小值。有些浏览器甚至不能完成——要求每秒100个 reflow 对大部分浏览器来说都不容易。低性能的电脑或者其他设备可能无法达到此种速度,在这些设备上动画可能非常慢甚至失去响应。

因此最好暂时把开发者的骄傲放在一边,牺牲流畅性而换取速度。把时间间隔改为50ms或把动画步长设为5个像素,会消耗更少的计算资源,在低性能设备上也能正常运行。

避免搜索大量节点

当需要查找节点时,尽量使用 DOM 内置方法和集合缩小搜索范围。如你想要定位某个包含某种属性的元素,可使用下面代码:

复制代码 代码如下:

var allElements = document.getElementsByTagName('*'); for( var i = 0; i < allElements.length; i++ ) { if( allElements[i].hasAttribute('someattr') ) { ... } }

即使没听说过 XPath 这样的高级技巧,也可以看出上面的代码有两个问题导致速度变慢。首先它搜索每一个元素,而不是尝试缩小搜索范围。其次即使已经找到所需元素上卖弄代码还继续搜索。如果已知要找的元素在 id 为 inhere的 div 中,最好使用下面的代码:

复制代码 代码如下:

var allElements = document.getElementById('inhere').getElementsByTagName('*'); for( var i = 0; i < allElements.length; i++ ) { if( allElements[i].hasAttribute('someattr') ) { ... break; } }

如果已知要找元素是 div 的直接子节点,则下面的代码速度更快:

复制代码 代码如下:

var allChildren = document.getElementById('inhere').childNodes; for( var i = 0; i < allChildren.length; i++ ) { if( allChildren[i].nodeType == 1 && allChildren[i].hasAttribute('someattr') ) { ... break; } }

基本的思想就是尽量避免逐个查看 DOM 节点。DOM 有很多更好更快的方法,如 DOM 2 Traversal TreeWalker,效率要高于递归查找 childNodes 集合。

使用 XPath 提高速度

假如需要基于 H2-H4 元素在 HTML 网页中创建目录。在 HTML 中标题元素可以出现在很多地方,因此无法使用递归函数获取这些元素。传统 DOM 可能使用如下方法:

复制代码 代码如下:

var allElements = document.getElementsByTagName('*'); for( var i = 0; i < allElements.length; i++ ) { if( allElements[i].tagName.match(/^h[2-4]$/i) ) { ... } }

若网页有超过2000个元素,此方法速度会很慢。如果支持 XPath,则可以使用一个快得多的方法,因为 XPath 查询引擎可比需被解释的JavaScript 更好的被优化。在有些情况下,XPath 速度可能会快2个数量级以上。下面代码和上面完成一样的功能,但使用 XPath因此速度要更快:

复制代码 代码如下:

var headings = document.evaluate( '//h2|//h3|//h4', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); var oneheading; while( oneheading = headings.iterateNext() ) { ... }

下面版本代码融合上述两种方法;在支持 XPath 的地方使用快速方法,在不支持时使用传统 DOM 方法:

if( document.evaluate ) { var headings = document.evaluate( '//h2|//h3|//h4', document, null, XPathResult.ORDERED_NODE_ITERATOR_TYPE, null ); var oneheading; while( oneheading = headings.iterateNext() ) { ... } } else { var allElements = document.getElementsByTagName('*'); for( var i = 0; i < allElements.length; i++ ) { if( allElements[i].tagName.match(/^h[2-4]$/i) ) { ... } } } 避免在遍历 DOM 时修改 DOM

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wdsjzs.html