摘要:訪問集合元素時(shí)使用局部變量對(duì)于任何類型的訪問,如果對(duì)同一個(gè)屬性或者方法訪問多次,最好使用一個(gè)局部變量對(duì)此成員進(jìn)行緩存。
三、DOM Scripting DOM編程
我們都知道對(duì)DOM操作的代價(jià)昂貴,這往往成為網(wǎng)頁應(yīng)用中的性能瓶頸。在解決這個(gè)問題之前,我們需要先知道什么是DOM,為什么他會(huì)很慢。
DOM in the Browser World 瀏覽器中的DOMDOM是一個(gè)獨(dú)立于語言的,使用XML和HTML文檔操作的應(yīng)用程序接口(API)。瀏覽器中多與HTML文檔打交道,DOM APIs也多用于訪問文檔中的數(shù)據(jù)。而在瀏覽器的實(shí)現(xiàn)中,往往要求DOM和JavaScript相互獨(dú)立。例如在IE中,JavaScript的實(shí)現(xiàn)位于庫文件jscript.dll中,而DOM的實(shí)現(xiàn)位于另一個(gè)庫mshtml.dll中(內(nèi)部代號(hào)Trident),這也是為什么IE內(nèi)核是Trident,IE前綴為-ms-,當(dāng)然,我們說的瀏覽器內(nèi)核其實(shí)英文名叫 Rendering Engine/Layout Engine,準(zhǔn)確翻譯應(yīng)該是渲染引擎/排版引擎/模板引擎(其實(shí)是一個(gè)東西);另外一個(gè)就是JavaScript引擎,ie6-8采用的是JScript引擎,ie9采用的是Chakra。而這是相分離的;Chrome中Webkit的渲染引擎和V8的JavaScript引擎,F(xiàn)irefox中Spider-Monkey的JavaScript引擎和Gecko的渲染引擎,都是相互分離的。
Inherently Slow 天生就慢
因?yàn)樯衔乃f的,瀏覽器渲染引擎和JavaScript引擎是相互獨(dú)立的,那么兩者之間以功能接口相互連接就會(huì)帶來性能損耗。曾有人把DOM和ECMAScript(JavaScript)比喻成兩個(gè)島嶼,之間以一座收費(fèi)橋連接,每次ECMAScript需要訪問DOM時(shí),都需要過橋,交一次“過橋費(fèi)”,操作DOM的次數(shù)越多,費(fèi)用就越高,這里的費(fèi)用我們可以看作性能消耗。因此請(qǐng)盡力減少操作DOM的次數(shù)。
1. DOM Access and Modification DOM訪問和修改
訪問DOM的代價(jià)昂貴,修改DOM的代價(jià)可能更貴,因?yàn)樾薷臅?huì)導(dǎo)致瀏覽器重新計(jì)算頁面的幾何變化,更更更貴的是采用循環(huán)訪問或者修改元素,特別是在HTML集合中進(jìn)行循環(huán)。簡(jiǎn)單舉例:
function innerHTMLLoop(){ for ( var count = 0; count < 100000; count++){ document.getElementById("p").innerHTML += "-"; } }
這時(shí)候,每執(zhí)行一次for循環(huán),就對(duì)DOM進(jìn)行了一次讀操作和寫操作(訪問和修改);此時(shí)我們可以采用另外一種方式:
function innerHTMLLoop(){ var content = ""; for ( var count = 0; count < 100000; count++){ content += "-"; } document.getElementById("p").innerHTML += content; }
我們使用了一個(gè)局部變量存儲(chǔ)更新后的內(nèi)容,在循環(huán)結(jié)束時(shí)一次性寫入,這時(shí)候只執(zhí)行了一次讀操作和寫操作,性能提升顯著。因此,盡量少的操作DOM,如果可以在JavaScript范圍內(nèi)完成的話。
2. innerHTML Versus DOM methods innerHTML與DOM方法
在老版本瀏覽器中,innerHTML更快但差別不大,更新的瀏覽器中,不相上下,最新的瀏覽器中,DOM方法更快,但依然差別不大。
3. Cloning Nodes 節(jié)點(diǎn)克隆
這樣的方法和DOM方法操作速度不相上下。
HTMLCollection是用于存放DOM節(jié)點(diǎn)引用的類數(shù)組對(duì)象。得到的方法有:document.getElementByName/document.getElementByClassName/document.getElementByTagName/document.querySelectAll/document.images/document.links/document.forms等;也有類似于document.forms[0].elements(頁面第一個(gè)表單的所有字段)等。
上面這些方法返回HTMLCollection對(duì)象,是一種類似數(shù)組的列表,沒有數(shù)組的方法,但是有l(wèi)enth屬性。在DOM標(biāo)準(zhǔn)中定義為:“虛擬存在,意味著當(dāng)?shù)讓游臋n更新時(shí),他們將自動(dòng)更新”。HTML集合實(shí)際上會(huì)去查詢文檔,更新信息時(shí),每次都要重復(fù)執(zhí)行這種查詢操作,這正是低效率的來源。
Expensive collections 昂貴的集合
先看個(gè)例子:
var oDiv = document.getElementByTagName("div"); for (var i = 0; i < oDiv.length; i++){ document.body.appendChild(document.createElement("div")) }
好吧,這是個(gè)死循環(huán),永遠(yuǎn)不會(huì)結(jié)束,但是這個(gè)過程中,每訪問一次oDiv.length,就會(huì)重新計(jì)算一遍其長(zhǎng)度,當(dāng)然,前提是對(duì)所有的div重新進(jìn)行一次遍歷,因此,在這里,我們最好使用一個(gè)變量暫存oDIv.length:
var oDivLen = document.getElementByTagName("div").length; for (var i = 0; i < oDivLen; i++){ document.body.appendChild(document.createElement("div")) }
從性能角度來講,這樣做會(huì)快很多。同時(shí),因?yàn)閷?duì)HTML集合的訪問比對(duì)數(shù)組訪問要更耗費(fèi)性能,因此在某些不得不多次訪問HTML集合的情況下,可以先將集合存儲(chǔ)為一個(gè)數(shù)組,然后對(duì)數(shù)組進(jìn)行訪問:
function toArray(htmlList){ for (var i = 0, htmlArray = [], len = htmlList.length; i < len; i++){ htmlArray[i] = htmlList[i]; } return htmlArray; }
當(dāng)然,這也需要額外的開銷,需要自己進(jìn)行權(quán)衡是否有必要這樣做。
Local variables when accessing collection elements 訪問集合元素時(shí)使用局部變量
對(duì)于任何類型的DOM訪問,如果對(duì)同一個(gè)DOM屬性或者方法訪問多次,最好使用一個(gè)局部變量對(duì)此DOM成員進(jìn)行緩存。特別是在HTML集合中訪問元素時(shí),如果多次對(duì)集合中的某一元素訪問,同樣需要將這個(gè)元素先進(jìn)行緩存。
DOM API提供了多種訪問文檔結(jié)構(gòu)特定部分的方法,去選擇最有效的API。
Crawling the DOM 抓取DOM
如果你可以通過:document.getElementByID();獲得某元素就不要去用document.getElementById().parentNode;這么麻煩去獲取。如果你可已通過nextSibling去獲取一個(gè)元素就不要通過childNodes去獲取,因?yàn)楹笳呤且粋€(gè)nodeList集合。
Element nodes 元素節(jié)點(diǎn)
DOM包含三個(gè)節(jié)點(diǎn)(也可以說是四個(gè)):元素節(jié)點(diǎn)、屬性節(jié)點(diǎn)、文本節(jié)點(diǎn)(以及注釋節(jié)點(diǎn));通常情況下,我們獲取到和使用的是元素節(jié)點(diǎn),但是我們通過childNodes、firstChild、nextSibling等方法獲取到的是所有節(jié)點(diǎn)的屬性,js中有一些其他的API可以用來只返回元素節(jié)點(diǎn)或者元素節(jié)點(diǎn)的某些屬性,我們可以用這些API取代那些返回整個(gè)全部節(jié)點(diǎn)或者節(jié)點(diǎn)屬性的API,例如:
childNodeschildrenchildNodes.lengthchildElementCountfirstChildfirstElementChildlastChildlastElementChildnextSiblingnextElementSiblingpreviousSiblingpreviousElementSibling
在所有的瀏覽器中,后者比前者要快,只不過IE中后面部分方法并不支持,比如IE6/7/8,只支持children方法。
The Selectors API 選擇器API
傳統(tǒng)的選擇器在性能方面問題不大,只不過應(yīng)用場(chǎng)景相對(duì)單一,當(dāng)我們用習(xí)慣了CSS選擇器之后,我們會(huì)覺得DOM給我們提供的選擇器讓我們抓狂。在querySelector/querySelectorAll之前,如果我們想要查找到元素下符合條件的另一元素時(shí),不得不使用類似下面的方法:document.getElementById("id1").getElementById("id2");,但如果你想獲取一個(gè)類名為class1或類名為class2的div的時(shí)候,不得不這么處理:
function getDivClass1(className1,className2){ var results = []; divs = document.getElementByTagName("div"); for (var i = 0,len = divs.length; i < len; i++){ _className = divs[i].className; if(_className === className1 || _className === className2){ results.push(divs[i]); } } return results; }
不僅僅是因?yàn)槿唛L(zhǎng)的代碼,多次對(duì)DOM進(jìn)行遍歷帶來的性能問題也不可小窺;不過在有了querySelector/querySelectorAll之后,這一切變得簡(jiǎn)單,減少對(duì)DOM的遍歷也帶來了性能的提升。上面兩個(gè)例子可以重寫如下:
document.querySelector("#id1 #id2"); document.querySelectorAll("div.className1,div.className2");
因此,如果可以,盡量使用querySelector/querySelectorAll吧。
Repaints and Reflows 重繪和重排(也稱回流)這涉及到一個(gè)比較古老的議題,瀏覽器在拿到服務(wù)器響應(yīng)時(shí)都干了什么。我查閱了相當(dāng)一部分資料(網(wǎng)上很多地方說法是不準(zhǔn)確的,包括一些問答、博客),去了解整個(gè)流程,這里簡(jiǎn)單的描述一下過程。更多細(xì)節(jié)可參考《瀏覽器的工作原理:新式網(wǎng)絡(luò)瀏覽器幕后揭秘》,原版地址(http://taligarsiel.com/Projec...)。
上文提到過,瀏覽器的實(shí)現(xiàn)一般包括渲染引擎和JavaScript引擎;二者是相互獨(dú)立的。
我們先從渲染引擎的角度來看一下在拿到服務(wù)器的文檔后的處理流程:
Parsing HTML to construct the DOM tree 解析HTML以構(gòu)建DOM tree
解析HTML文檔,將各個(gè)標(biāo)記逐個(gè)轉(zhuǎn)化為DOM tree 上的DOM節(jié)點(diǎn);當(dāng)然并不是一一對(duì)應(yīng);類似于head這樣的標(biāo)記是在DOM tree上是沒有對(duì)應(yīng)的節(jié)點(diǎn)的。在這個(gè)過程中,同時(shí)被解析的還包括外部CSS文件以及樣式元素中的樣式數(shù)據(jù),這些數(shù)據(jù)信息被準(zhǔn)備好進(jìn)行下一步工作。
Render tree construction 構(gòu)建render tree
在DOM tree構(gòu)建過程中,CSS文件同時(shí)被解析,DOM tree上每一個(gè)節(jié)點(diǎn)的對(duì)應(yīng)的顏色尺寸等信息被保存在另一個(gè)被稱作rules tree的對(duì)象中(具體實(shí)現(xiàn)方式webkit和gecho是不一樣的,可參考上文提到過的《瀏覽器的工作原理》)。DOM tree和rules tree兩者一一對(duì)應(yīng),均構(gòu)建完成之后,render tree也就構(gòu)建完成了。
Layout of the render tree 布局render tree
依據(jù)render tree中的節(jié)點(diǎn)信息和對(duì)應(yīng)的rules中的尺寸信息(包括display屬性等),為每一個(gè)節(jié)點(diǎn)分配一個(gè)應(yīng)該出現(xiàn)在屏幕上的確切坐標(biāo)。
Painting the render tree 繪制render tree
就是將已布局好的節(jié)點(diǎn),加上對(duì)應(yīng)的顏色等信息,繪制在頁面上。
當(dāng)然,瀏覽器并不會(huì)等到全部的HTML文檔信息都拿到之后才進(jìn)行解析,也不會(huì)等到全部解析完畢之后才會(huì)進(jìn)行構(gòu)建render tree和設(shè)置布局。渲染引擎可能在接收到一部分文檔后就開始解析,在解析了一部分文檔后就開始進(jìn)行構(gòu)建render tree和layout render tree。
JavaScript引擎的工作:
正常的流程中,渲染引擎在遇到標(biāo)記時(shí),會(huì)停止解析,由JavaScript引擎立即執(zhí)行腳本,如果是外部則立即進(jìn)行下載并執(zhí)行,這期間渲染引擎是不工作的。如果腳本被標(biāo)注為defer時(shí),腳本立即進(jìn)行下載,但暫不執(zhí)行,而且這期間也不會(huì)阻塞渲染引擎的渲染,腳本會(huì)在文檔解析完畢之后執(zhí)行;如果腳本被標(biāo)注為async時(shí),腳本立即進(jìn)行下載,下載完成后會(huì)立即執(zhí)行,只不過這個(gè)過程和渲染時(shí)兩個(gè)線程進(jìn)行的,二者是異步執(zhí)行,同樣不會(huì)影響頁面渲染。defer和async二者的區(qū)別是:雖然都是立即下載(這兩個(gè)都只作用于外部腳本),但是前者是在文檔解析完畢后執(zhí)行,后者是下載完成后立即執(zhí)行,因此前者可以保證腳本按照順序執(zhí)行,而后者誰先下載完誰先執(zhí)行會(huì)導(dǎo)致依賴關(guān)系混亂。
注:關(guān)于async和defer,在查閱資料后的說法見上文。但在我自己編寫DEMO測(cè)試的過程中,發(fā)現(xiàn)在Chrome中偶爾會(huì)全部阻塞,偶爾都不阻塞,最多的是腳本以上的文檔不阻塞,以下的文檔被阻塞;IE/FireFox中完全不鳥這倆屬性,直接等到腳本執(zhí)行完畢才出現(xiàn)頁面。
說回重繪和重排,
先說重排,當(dāng)render tree中的一部分因?yàn)樵氐某叽?、布局、顯示隱藏等改變而需要重新構(gòu)建render tree時(shí),此時(shí)就叫重排,也就是重新構(gòu)建render tree;會(huì)引起重排的場(chǎng)景包括:添加或者刪除可見的DOM元素、元素位置改變、元素尺寸改變(邊距、填充、邊框、寬高等)、內(nèi)容改變(因此引起尺寸改變)、頁面渲染初始化(首次加載頁面)、瀏覽器窗口尺寸改變;還有很重要的一點(diǎn)就是在嘗試獲取頁面元素的尺寸時(shí)也會(huì)強(qiáng)制引發(fā)重排(因?yàn)橹嘏诺倪^程會(huì)重新計(jì)算元素的尺寸,所以為保證獲得最新的尺寸信息,會(huì)先強(qiáng)制進(jìn)行重排),例如:offsetTop/offsetLeft/offsetWidth/offsetHeight/scrollTop/scrollLeft/scrollWidth/scrollHeight/clientTop/clientLeft/clientWidth/clientHeight/width/height/getComputedStyle()/currentStyle()。
重繪一般發(fā)生在元素的外觀變化時(shí),首先重排一定會(huì)引起重繪,當(dāng)元素的顏色/背景色/透明度/visibility屬性等發(fā)生變化也會(huì)引起重繪。
Queuing and Flushing Render Tree Changes 查詢并刷新render tree改變
前文我們知道了構(gòu)建render tree過程中,會(huì)先對(duì)CSS以及樣式元素中的樣式數(shù)據(jù)進(jìn)行解析計(jì)算,在引發(fā)重排時(shí),會(huì)對(duì)樣式數(shù)據(jù)重新計(jì)算,性能問題就出現(xiàn)在大量計(jì)算的過程中,在大多數(shù)的瀏覽器中,會(huì)通過隊(duì)列化修改和批量顯示優(yōu)化重排的過程,但是我們剛所提到的嘗試獲取頁面尺寸信息會(huì)強(qiáng)制引發(fā)重排,類似下面代碼:
var computedValue, tmp = "", bodystyle = document.body.style; if (document.body.currentStyle) { computedValue = document.body.currentStyle; }else{ computedValue = document.defaultView.getComputedStyle(document.body, ""); } bodystyle.color = "red"; tmp = computedValue.backgroundColor; bodystyle.color = "white"; tmp = computedValue.backgroundImage; bodystyle.color = "green"; tmp = computedValue.backgroundAttachment;
上面示例中,body的字體顏色被改變了三次,每次改變后都對(duì)body的樣式信息進(jìn)行了查詢,雖然查詢的信息和字體顏色無關(guān),但是瀏覽器會(huì)因此刷新渲染隊(duì)列并進(jìn)行重排,所以共進(jìn)行了三次重排,也理所當(dāng)然的進(jìn)行了三次重繪,這里可以改進(jìn)一下:
var computedValue, tmp = "", bodystyle = document.body.style; if (document.body.currentStyle) { computedValue = document.body.currentStyle; }else{ computedValue = document.defaultView.getComputedStyle(document.body, ""); } bodystyle.color = "red"; bodystyle.color = "white"; bodystyle.color = "green"; tmp = computedValue.backgroundColor; tmp = computedValue.backgroundImage; tmp = computedValue.backgroundAttachment;
在下面的例子中,實(shí)際上引起了一次重排和兩次重繪,首先bodystyle.color的三次變化被批量化一次處理,只進(jìn)行了一次重繪,接著對(duì)computedValue的訪問批量處理,進(jìn)行了一次重排,接著此次重排又引起一次重繪。速度要比優(yōu)化之前的更快。因此,盡量不要在布局信息發(fā)生變化時(shí)對(duì)元素尺寸進(jìn)行查詢。
Minimizing Repaints and Reflows 最小化重繪和重排
上面的例子其實(shí)就是減小重繪重排的一種方法,盡量將對(duì)DOM和風(fēng)格改變的操作放在一起,在一次批量修改中完成。
① style changes 改變風(fēng)格
先舉例:
var oDiv = document.getElementById("div"); oDib.style.borderLeft = "1px"; oDib.style.padding = "10px"; oDib.style.width = "100px";
這里對(duì)oDiv進(jìn)行了三次改變,每次改變都涉及到元素的幾何屬性,雖然大多數(shù)瀏覽器進(jìn)行了優(yōu)化,只進(jìn)行一次重排,但部分老式瀏覽器中,效率很低,而且如果在此時(shí)進(jìn)行了布局信息查詢,會(huì)導(dǎo)致三次重排的進(jìn)行,我們可以換一種風(fēng)格實(shí)現(xiàn):
var oDiv = document.getElementById("div"); oDiv.style.cssText = "border-left: 1px;padding: 10px;width: 100px;";
優(yōu)化后的代碼,只進(jìn)行一次重排,但是會(huì)覆蓋原有的樣式信息(這里的覆蓋會(huì)清空原來所有的行內(nèi)樣式信息),因此也可以這么寫:
oDiv.style.cssText += ";border-left: 1px;padding: 10px;width: 100px;";
當(dāng)然,我們也可以通過對(duì)類名的修改,類名事先在CSS中定義了對(duì)應(yīng)的樣式信息,來達(dá)到修改樣式的需求,比如:
var oDiv = document.getElementById("div"); oDiv.className += "current";
② Batching DOM changes 批量修改DOM
原文翻譯是批量修改DOM,我的理解是批量DOM修改,這種方法是將會(huì)被多次修改的DOM元素,先從文檔流摘除,然后批量修改,然后帶回文檔,這樣僅僅在摘除和帶回時(shí)發(fā)生兩次重排,中間的多次修改,并不會(huì)帶來重排。將元素從文檔摘除有很多方法,比如將元素隱藏(dispaly:none;)、DOM之外新建一個(gè)文檔片段修改后添加到原節(jié)點(diǎn)位置。
③ Caching Layout Information 緩沖布局信息
比如我們通過setTimeout實(shí)現(xiàn)一個(gè)動(dòng)畫:元素每10毫秒向右下方移動(dòng)1px;從100X100移動(dòng)到500X500:
myElement.style.left = 1 + myElement.offsetLeft + "px"; myElement.style.top = 1 + myElement.offsetTop + "px"; if (myElement.offsetLeft >= 500){ stopAnimation(); }
代碼中,我們每次查詢myElement.offsetLeft/myElement.offsetTop值的時(shí)候,都引起了一次頁面重排,一次循環(huán)中,至少進(jìn)行了三次重排,性能糟糕的不要不要的,我們可以通過優(yōu)化,將myElement.offsetLeft/myElement.offsetTop的值緩存起來:
var current = myElement.offsetLeft;
循環(huán)內(nèi):
current++; myElement.style.left = current + "px"; myElement.style.top = current + "px"; if (current >= 500) { stopAnimation(); }
將myElement.offsetLeft緩存起來,初始查詢一次,之后不再進(jìn)行查詢,只引用變量current;而且在瀏覽器的優(yōu)化后,每次循環(huán)只進(jìn)行了一次重排,性能提升不是一點(diǎn)。
④ Take Elements Out of the Flow for Animations 將元素提出動(dòng)畫流
顯示/隱藏部分頁面、折疊/展開動(dòng)畫是很常見的動(dòng)畫交互模式。很多時(shí)候展開/折疊動(dòng)畫,會(huì)將頁面一部分?jǐn)U大,將下面的部分向下推開,這樣,會(huì)帶來不僅僅是展開部分的重排,包括下面的部分全部重排,而重排的性能消耗,和影響的渲染樹程度有關(guān),因此我們可以減少對(duì)頁面影響部分來實(shí)現(xiàn)減小重排帶來的性能消耗。
(1) 使用絕對(duì)坐標(biāo)定位頁面動(dòng)畫部分,使其脫離于頁面文檔布局流之外,這樣它的改變對(duì)其他文檔的位置尺寸等信息無影響,不會(huì)引起其他部分重排
(2) 展開動(dòng)作只在動(dòng)畫元素上進(jìn)行,其下面的元素不隨著動(dòng)畫元素展開推移,只是被遮蓋,這樣也不會(huì)引起大范圍的渲染樹重新計(jì)算
(3) 在動(dòng)畫結(jié)束后,再將下面的元素一次性移動(dòng),而不是動(dòng)畫過程中慢慢移動(dòng)。
⑤ IE and :hover IE和:hover
IE7+全面支持:hover,但是大量元素使用:hover會(huì)帶來嚴(yán)重的性能問題。比如一個(gè)大型的表格,使用tr:hover來使鼠標(biāo)光標(biāo)所在行高亮?xí)r,會(huì)使cpu的使用率提升80%-90%。因此應(yīng)當(dāng)盡量避免大量元素使用:hover屬性。
當(dāng)頁面上存在大量元素,而且每個(gè)元素都有一個(gè)或者多個(gè)事件句柄與之綁定的時(shí)候,可能會(huì)影響性能,因?yàn)閽旖用總€(gè)句柄都是有代價(jià)的,更多的頁面標(biāo)記和JavaScript代碼,運(yùn)行期需要訪問和修改更多的DOM節(jié)點(diǎn)。更重要的是事件掛載發(fā)生在onload事件中,而這個(gè)時(shí)間段是有很多事要處理的,無形中影響到其他事件的處理。但是你給頁面上一百個(gè)元素每人綁定了一個(gè)點(diǎn)擊事件,但是可能只有十個(gè)可能會(huì)被真正點(diǎn)擊調(diào)用,做了90%的無用功。
我們可以通過事件托管來處理這類需求,原理是事件冒泡,也就是在包裹元素上掛接一個(gè)句柄,用于處理其子元素發(fā)生的所有事件。比如在點(diǎn)擊時(shí),判斷當(dāng)前標(biāo)簽的類名,不同類名執(zhí)行對(duì)應(yīng)的操作,這樣既不用給每一個(gè)元素綁定事件句柄,也實(shí)現(xiàn)了每個(gè)元素的點(diǎn)擊事件處理。Jquery中的on可以給動(dòng)態(tài)添加的元素綁定事件也是利用了事件托管的辦法。
高性能JavaScript閱讀簡(jiǎn)記(一)
高性能JavaScript閱讀簡(jiǎn)記(二)
高性能JavaScript閱讀簡(jiǎn)記(三)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/51104.html
摘要:對(duì)于直接量和局部變量的訪問性能差異微不足道,性能消耗代價(jià)高一些的是全局變量數(shù)組項(xiàng)對(duì)象成員。當(dāng)一個(gè)函數(shù)被創(chuàng)建后,作用域鏈中被放入可訪問的對(duì)象。同樣會(huì)改變作用域鏈,帶來性能問題。 早前閱讀高性能JavaScript一書所做筆記。 一、Loading and Execution 加載和運(yùn)行 從加載和運(yùn)行角度優(yōu)化,源于JavaScript運(yùn)行會(huì)阻塞UI更新,JavaScript腳本的下載、解析...
摘要:對(duì)于直接量和局部變量的訪問性能差異微不足道,性能消耗代價(jià)高一些的是全局變量數(shù)組項(xiàng)對(duì)象成員。當(dāng)一個(gè)函數(shù)被創(chuàng)建后,作用域鏈中被放入可訪問的對(duì)象。同樣會(huì)改變作用域鏈,帶來性能問題。 早前閱讀高性能JavaScript一書所做筆記。 一、Loading and Execution 加載和運(yùn)行 從加載和運(yùn)行角度優(yōu)化,源于JavaScript運(yùn)行會(huì)阻塞UI更新,JavaScript腳本的下載、解析...
摘要:訪問集合元素時(shí)使用局部變量對(duì)于任何類型的訪問,如果對(duì)同一個(gè)屬性或者方法訪問多次,最好使用一個(gè)局部變量對(duì)此成員進(jìn)行緩存。 三、DOM Scripting DOM編程 我們都知道對(duì)DOM操作的代價(jià)昂貴,這往往成為網(wǎng)頁應(yīng)用中的性能瓶頸。在解決這個(gè)問題之前,我們需要先知道什么是DOM,為什么他會(huì)很慢。 DOM in the Browser World 瀏覽器中的DOM DOM是一個(gè)獨(dú)立于語言...
摘要:移植到中的一個(gè)典型的達(dá)夫設(shè)備的例子為一個(gè)很長(zhǎng)很長(zhǎng)的數(shù)組。但是達(dá)夫設(shè)備最初這種詭異的寫法和思路,還是驚艷了很多人的,值得我們思考。高性能閱讀簡(jiǎn)記一高性能閱讀簡(jiǎn)記二高性能閱讀簡(jiǎn)記三 四、Aligorithms and Flow Control 算法和流程控制 1、Loops 循環(huán) a、避免使用for/in循環(huán)在JavaScript標(biāo)準(zhǔn)中,有四種類型循環(huán)。for、for/in、while、...
閱讀 1860·2023-04-26 02:51
閱讀 2901·2021-09-10 10:50
閱讀 3132·2021-09-01 10:48
閱讀 3691·2019-08-30 15:53
閱讀 1857·2019-08-29 18:40
閱讀 433·2019-08-29 16:16
閱讀 2057·2019-08-29 13:21
閱讀 1841·2019-08-29 11:07