2013-10-08 47 views
12

下面的代碼說明了這個問題,改變讀/寫順序導致執行時間差異很大(使用Chrome,Firefox和IE測試):爲什麼DOM讀/寫操作的微小重新排序會導致巨大的性能差異

// 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:
慢版:〜2000毫秒
快版本:〜25ms

我認爲這與t他在每種情況下瀏覽器迴流的數量。在緩慢的情況下,每次寫操作都會發生迴流。但是,在快速情況下,迴流只會在最後發生一次。但我不確定,我不明白它爲什麼會這樣工作(當操作是獨立的時候)。

編輯:我用InnerText屬性,而不是clientWidthStyle.Width,我使用谷歌瀏覽器(http://jsfiddle.net/pindexis/CW2BF/7/)時,得到了同樣的行爲。但是,使用InnerHTML時,幾乎沒有差異(http://jsfiddle.net/pindexis/8E5Yj/)。

EDIT2:我開一個討論有關的innerHTML/innerText屬性問題,對於那些有興趣:why does replacing InnerHTML with innerText causes >15X drop in performance

回答

8

的操作是不是獨立的。

的反流必須發生在風格或內容大小改變位置或需要的尺寸,或者是因爲你要求的尺寸或因爲屏幕必須被更新(當你的代碼完成)。

div.clientWidth是一個隱藏的函數調用。當你請求這個值時,你實際上要求一個最新的值,因此,當樣式改變時,你會立即觸發迴流。

在「快速」情況下,在重新繪製屏幕或請求尺寸之前沒有理由進行迴流。在這種情況下,只需要一次迴流。

+0

因此,當請求下一個'div'的'clientWidth'時,是否改變了之前'div'的寬度,以觸發迴流? –

+0

更改div寬度會改變回流狀態(請參閱http://www-archive.mozilla.org/newlayout/doc/reflow.html)。但是,迴流不一定要立即完成,只有在需要結果的時候。當你沒有請求寬度時,直到線程結束時纔會發生迴流(注意,你不能真正依靠這個,我記得Opera注意到如果腳本執行很長,可能會更快地發生迴流) 。由於迴流並不總是在整個頁面上,所以會發生更難以預測的事情。 –

+0

請記住,所有這些都是依賴於實現的,但是清晰地變化並且立即在循環中讀取是一種最糟糕的情況。 –

相關問題