13

以下代码说明了问题,更改读/写顺序会导致执行时间有很大差异(使用 Chrome、Firefox 和 IE 测试):

// read->write->read->write...
function clearSlow(divs){
    Array.prototype.forEach.call(divs, function(div) {
        contents.push(div.clientWidth);
        div.style.width = "10px";
    });
}
// read->read->...->write->write...
function clearFast(divs){
    Array.prototype.forEach.call(divs, function(div) {
        contents.push(div.clientWidth);
    });
    Array.prototype.forEach.call(divs, function(div) {
        div.style.width = "10px";
    });
}

这是完整示例http://jsfiddle.net/Dq3KZ/2/的 JSFiddle 。

我的 n=100 的结果:
慢速版本:~35ms
快速版本:~2ms

对于 n=1000:
慢速版本:~2000ms
快速版本:~25ms

我认为这与每种情况下浏览器重排的数量有关。在慢速场景中,每次写入操作都会发生回流。但是,在快速方案中,回流仅在最后发生一次。但我不确定,也不明白为什么它会那样工作(当操作是独立的时)。

编辑:我使用InnerTextproperty 而不是clientWidthand Style.Width,我在使用 Google Chrome ( http://jsfiddle.net/pindexis/CW2BF/7/ ) 时得到了相同的行为。但是,InnerHTML使用时几乎没有区别(http://jsfiddle.net/pindexis/8E5Yj/)。

Edit2:我已经为感兴趣的人开启了关于 innerHTML/innerText 问题的讨论:为什么用 innerText 替换 InnerHTML 会导致性能下降 15 倍以上

4

1 回答 1

9

操作不是独立的。

当样式或内容大小发生更改并且需要位置或尺寸时,必须发生重排,因为您请求尺寸或因为必须更新屏幕(当您的代码完成时)。

div.clientWidth是一个隐藏的函数调用。当您请求此值时,实际上您请求的是最新值,因此,随着样式的更改,您会立即触发重排。

在“快速”的情况下,在重新绘制屏幕或您请求尺寸之前,没有理由进行回流。在这种情况下,实际上只需要一次回流。

于 2013-10-08T14:56:17.353 回答