摘要:而像和會(huì)增加作用域鏈的長(zhǎng)度,所以也會(huì)降低性能。但是用獲取一些屬性時(shí),會(huì)不由自主地強(qiáng)迫隊(duì)列中的所有渲染事件前不完成。在條件增加時(shí),所帶來(lái)的性能負(fù)擔(dān)要高于,因此建議使用。它代價(jià)昂貴,且容易失控。
正巧看到在送書(shū),于是乎找了找自己博客上記錄過(guò)的一些東西來(lái)及其無(wú)恥的蹭書(shū)了~~~
小廣告:更多內(nèi)容可以看我的博客
以下內(nèi)容均來(lái)自《高性能JavaScript》
JavaScript文件加載管理瀏覽器中的JavaScript代碼是一個(gè)棘手的問(wèn)題,因?yàn)榇a執(zhí)行會(huì)阻塞瀏覽器,比如界面繪制。每次遇到標(biāo)簽,瀏覽器都會(huì)停下來(lái)等待代碼下載并執(zhí)行,然偶再繼續(xù)處理其他部分。我們可以通過(guò)如下幾種方法來(lái)減少JavaScript文件對(duì)性能的影響
將JS文件放在頁(yè)面底部將所有標(biāo)簽放置在頁(yè)面的底部,緊靠body關(guān)閉標(biāo)簽
的上方。這樣可以保證頁(yè)面在腳本運(yùn)行之前完成解析
將JS文件打包將JS文件打包,頁(yè)面的標(biāo)簽越少,頁(yè)面的加載速度越快,響應(yīng)也越迅速。無(wú)論外部腳本文件還是內(nèi)斂代碼都是如此
使用非阻塞方式下載在標(biāo)簽中添加defer屬性
動(dòng)態(tài)創(chuàng)建元素,用它下載并執(zhí)行代碼
用XHR對(duì)象下載代碼,并注入到頁(yè)面中
數(shù)據(jù)訪問(wèn) 四種訪問(wèn)方式在JavaScript中,數(shù)據(jù)存儲(chǔ)位置可以對(duì)代碼整體性能產(chǎn)生重要影響,有四種數(shù)據(jù)訪問(wèn)類型:直接量,變量,數(shù)組項(xiàng),對(duì)象成員,這些訪問(wèn)方式性能不同
直接量和局部變量訪問(wèn)速度很快,而數(shù)組項(xiàng)和對(duì)象成員需要更長(zhǎng)的時(shí)間
作用域鏈和閉包的訪問(wèn)速度在函數(shù)內(nèi)部訪問(wèn)變量時(shí),會(huì)順著作用域鏈向上查找,直到找到為止,這也意味著作用域鏈越長(zhǎng),平均的查找時(shí)間也就越長(zhǎng)。而像with和try-catch會(huì)增加作用域鏈的長(zhǎng)度,所以也會(huì)降低性能。由此可以得知,訪問(wèn)全局變量很慢,因?yàn)樗麄冊(cè)谧饔糜蜴湹淖詈笠画h(huán)
原型鏈訪問(wèn)訪問(wèn)對(duì)象的屬性的時(shí)候,我們有時(shí)候會(huì)需要遍歷原型鏈,這也意味著原型鏈越長(zhǎng),查找元素的平均效率就越低,變量所在的原型在原型鏈中越深,訪問(wèn)越慢
DOM當(dāng)瀏覽器下載完所有的HTML、JavaScript、CSS、圖片之后,它會(huì)解析文件并創(chuàng)建兩個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu):一棵DOM樹(shù)和一棵渲染樹(shù)
每個(gè)需要被顯示的DOM樹(shù)節(jié)點(diǎn)在渲染樹(shù)中至少有一個(gè)節(jié)點(diǎn)(隱藏的DOM節(jié)點(diǎn)自然在渲染樹(shù)中沒(méi)有節(jié)點(diǎn)),渲染樹(shù)上的點(diǎn)被稱為框或者盒,根據(jù)CSS模型定義,將頁(yè)面元素看做一個(gè)具有填充、邊距、邊框和位置的盒。一旦DOM樹(shù)和渲染樹(shù)構(gòu)造完畢,瀏覽器就可以繪制頁(yè)面上的元素了。
當(dāng)DOM改變影響到元素的幾何屬性(寬和高),瀏覽器就需要重新計(jì)算元素的幾何屬性。如果這個(gè)元素的改變影響到其他元素,瀏覽器會(huì)使渲染樹(shù)上收到影響的部分失效,然后重構(gòu)渲染樹(shù)。這就是回流(也叫重排版)。重排版完成時(shí),瀏覽器在一個(gè)重繪進(jìn)程中重新繪制屏幕上受影響的部分
當(dāng)然并不是所有DOM改變都會(huì)影響到幾何屬性,比如改變背景顏色之類的,這種情況下就只會(huì)觸發(fā)重繪
回流和重繪都是負(fù)擔(dān)很重的操作,會(huì)導(dǎo)致瀏覽器阻塞,所以需要盡可能避免
何時(shí)觸發(fā)回流添加或刪除可見(jiàn)的DOM元素
元素位置的改變
元素尺寸的改變(border、padding、margin、height、width)
內(nèi)容改變
最初頁(yè)面渲染
瀏覽器窗口改變尺寸
查詢并刷新渲染樹(shù)的改變因?yàn)橛?jì)算量與每次回流有關(guān),大多數(shù)瀏覽器會(huì)通過(guò)一個(gè)渲染隊(duì)列來(lái)進(jìn)行優(yōu)化。但是用JavaScript獲取一些DOM屬性時(shí),會(huì)(不由自主地)強(qiáng)迫隊(duì)列中的所有渲染事件前不完成。比如獲取如下屬性:
* offsetTop, offsetLeft, offsetWidth, offsetHeight
* scrollTop, scrollLeft, scrollWidth, scrollHeight
* clientTop, clientLeft, clientWidth, clientHeight
* getComputedStyle() (在IE中為currentStyle)
為了讓這些屬性返回正確的值,瀏覽器不得不運(yùn)行渲染隊(duì)列中所有的渲染事件,這樣才能保證值的正確。所以盡量減少這些屬性的訪問(wèn)
判斷 if-else多個(gè)if-else執(zhí)行的時(shí)候,其會(huì)順序檢索每一個(gè)條件,直到所有條件檢索完或檢索到匹配的條件。所以我們可以通過(guò)樹(shù)的形式組織if語(yǔ)句,如下面代碼:
if(con === 1) {return result1;} else if(con === 2) {return result2;} else if(con === 3) {return result3;} else if(con === 4) {return result4;} else if(con === 5) {return result5;} else if(con === 6) {return result6;} else if(con === 7) {return result7;} else if(con === 8) {return result8;} else if(con === 9) {return result9;}
這段代碼就會(huì)依次判斷con是否等于1,2,3,4,5,6,7,8,9,如果是9的話,就會(huì)判斷9次,我們可以將其改為:
if (con <= 3){ if(con === 1) {return result1;} else if(con === 2) {return result2;} else {return result3;} } else if(con > 3 && con <= 6){ if(con === 4) {return result4;} else if(con === 5) {return result5;} else {return result6;} } else if(con <= 9){ if(con === 7) {return result7;} else if(con === 8) {return result8;} else {return result9;} }
這樣我們通過(guò)三叉樹(shù)的形式,就可以減少查找次數(shù)了,比如這里查找9次,分別判斷 0~3,3~6,6~9,7,8,9,只需要6次
if-else除了通過(guò)這種樹(shù)形組織編碼以外,還有一個(gè)優(yōu)化的地方。由于其順序判斷的邏輯,我們可以根據(jù)概率來(lái),將概率比較大的判斷放在前面,概率較小的放在后面,這樣也可以減少平均查找長(zhǎng)度
switch事實(shí)證明,大多數(shù)情況下switch比if-else更快,但是只有條件題數(shù)量很大的時(shí)候,才能明顯更快。if-else在條件增加時(shí),所帶來(lái)的性能負(fù)擔(dān)要高于switch,因此建議使用switch。不過(guò)switch只是用來(lái)判斷幾個(gè)不同的離散值,并沒(méi)有if-else能判斷離散值或值域那樣的靈活性
打表法可以使用打表的形式來(lái)做,把所有的處理函數(shù)放在一個(gè)數(shù)組中,然后將條件作為鍵,這種方法比switch和if-else都要快,而且在新增條件時(shí),不會(huì)帶來(lái)額外的性能開(kāi)銷
遞歸很多算法都是遞歸實(shí)現(xiàn),由于遞歸會(huì)多次觸發(fā)函數(shù)調(diào)用,而函數(shù)調(diào)用也是需要開(kāi)銷的(比如創(chuàng)建運(yùn)行期上下文、壓運(yùn)行期棧、創(chuàng)建AO、復(fù)制作用域鏈、銷毀AO、弾棧等等),所以盡量將遞歸轉(zhuǎn)變?yōu)檠h(huán)。而運(yùn)行期棧在很多瀏覽器中也有深度限制,當(dāng)?shù)竭_(dá)運(yùn)行期棧的最大深度時(shí),瀏覽器有各自的處理方式,但都是按照錯(cuò)誤進(jìn)行處理
字符串 不同的拼接方法字符串拼接有很多不同的方法:
1. 使用+直接拼接
2. 使用+=拼接
3. 使用Array.join()拼接
4. 使用String.concat()拼接
使用+和+=時(shí),不同的瀏覽器會(huì)做不同程度的優(yōu)化,如果在IE7和他之前的瀏覽器,優(yōu)化做的不好,比如如下操作:
str += "one" + "two"
實(shí)際上會(huì)執(zhí)行如下步驟:
1. 內(nèi)存中創(chuàng)建一個(gè)臨時(shí)變量
2. 將這個(gè)臨時(shí)變量賦值成"onetow"
3. 臨時(shí)字符串與str拼接
4. 將結(jié)果賦予str
而如果改成如下這樣:
str += "one" str += "two"
這樣就可以避免創(chuàng)建臨時(shí)字符串,可一定程度加快性能
或者使用如下方式:
str = str + "one" + "two"
但是如果使用下面這種方式:
str = "one" + str + "two"
則無(wú)法確定是否有優(yōu)化。不同的瀏覽器分配內(nèi)存方式不一樣,IE以外的瀏覽器,會(huì)嘗試擴(kuò)展表達(dá)式左端字符串的內(nèi)存,然后簡(jiǎn)單的將第二個(gè)字符串拷到它的尾部,這樣就會(huì)創(chuàng)建一個(gè)臨時(shí)字符串存放one{str原本內(nèi)容},導(dǎo)致性能降低
瀏覽器優(yōu)化很多瀏覽器會(huì)在編譯時(shí)對(duì)連續(xù)相加的字符串進(jìn)行拼接,以此來(lái)對(duì)運(yùn)行時(shí)優(yōu)化,比如:
str += "one" + "two"
會(huì)被優(yōu)化成
str += "onetwo"IE7-中的字符串連接
IE7-中使用+和+=連接很慢,而使用Array.join()方式則快得多,這也是IE7-瀏覽器中唯一高效的連接大量字符串的途徑
String.concat這種方法很慢,盡量不要使用
正則表達(dá)式優(yōu)化 正則表達(dá)式的工作原理正則表達(dá)式處理經(jīng)過(guò)如下幾個(gè)步驟:
1. 編譯
2. 設(shè)置起始位置
3. 匹配每個(gè)正則表達(dá)式的字元
4. 匹配成功或失敗
正則表達(dá)式實(shí)現(xiàn)中,回溯是基本組成部分。它代價(jià)昂貴,且容易失控?;厮菔钦齽t表達(dá)式性能的唯一因素
正則表達(dá)式在匹配時(shí),會(huì)在一個(gè)有多個(gè)分支的地方建立標(biāo)記點(diǎn),然后從左到右遍歷所有的分支,如果分支符合,就會(huì)前進(jìn)道下一個(gè)標(biāo)記點(diǎn),如果所有分支都不符合,就會(huì)回溯到上一個(gè)標(biāo)記點(diǎn),嘗試上一標(biāo)記點(diǎn)的其他分支。在嘗試上一標(biāo)記點(diǎn)的其它分支時(shí),這一標(biāo)記點(diǎn)如果需要,還會(huì)全部重新嘗試
回溯失控當(dāng)一個(gè)正則表達(dá)式占用瀏覽器上秒,或者更長(zhǎng)時(shí)間,很有肯那個(gè)就是回溯失控了,原因很有可能是出現(xiàn)了.*?這種非貪婪匹配,導(dǎo)致幾乎每一個(gè)字符都會(huì)被作為標(biāo)記點(diǎn)進(jìn)行嘗試
此類問(wèn)題的解決辦法是盡可能具體地指出分隔符之間的字符匹配形式,或者使用前瞻表達(dá)式
嵌套量詞導(dǎo)致性能下降嵌套量詞可能極大的加大分支的數(shù)量,比如一個(gè)正則表達(dá)式A+A+B顯然沒(méi)有AA+B好,比如匹配AAAAAAAAAAAAAAB時(shí),前者產(chǎn)生的分支要比后者多得多
一些建議關(guān)注如何讓匹配更快失敗:正則表達(dá)式慢往往不是因?yàn)槌晒β?,而是失敗慢,因?yàn)槭?huì)查找所有的情況
以簡(jiǎn)單的,必須的字元開(kāi)始:這樣可以加快失敗的匹配,如果這個(gè)開(kāi)始字元都不匹配,后面的標(biāo)記點(diǎn)就不會(huì)被匹配了
編寫(xiě)兩次模板,使他們后面的資源互相排斥:當(dāng)字元與鄰近的子表達(dá)式能夠重疊匹配時(shí),路徑將顯著正價(jià),所以需要將其具體化
減少分之?dāng)?shù)量,縮小它們的范圍:直接使用正則表達(dá)式中已有的類(如w,d)比使用|要快
使用非捕獲分組:捕獲分組花費(fèi)時(shí)間和內(nèi)存用于記錄后向引用,而使用后非捕獲性分組則避免這種開(kāi)銷
將正則表達(dá)式分層,先捕獲感興趣的文字,然后再使用新的正則表達(dá)式處理
暴露所需的字元,盡量簡(jiǎn)單地判斷出那些必須的字元
使用適當(dāng)?shù)牧吭~,貪婪量詞和懶惰量詞在匹配同樣字符串時(shí)過(guò)程是不同的,在確保正確的前提下,選擇回溯次數(shù)更少的量詞可以提高性能
將正則表達(dá)式賦給變量,以重用他們。正則表達(dá)式創(chuàng)建時(shí),需要對(duì)他們進(jìn)行編譯,這個(gè)編譯也會(huì)有額外的開(kāi)銷
將復(fù)雜的正則表達(dá)式拆分成簡(jiǎn)單的片段,避免使用一個(gè)表達(dá)式做太多的工作,可以通過(guò)兩個(gè)或多個(gè)正則表達(dá)式來(lái)解決
UI線程相關(guān)建議的一次JavaScript執(zhí)行時(shí)間不超過(guò)100ms(最好在50ms)以內(nèi),可以通過(guò)setTimeout和setInterval來(lái)將任務(wù)進(jìn)行分解,加入到UI線程中。其實(shí)這個(gè)思想和JavaScript引擎的垃圾回收器的迭代處理相似
AJAXAJAX獲取數(shù)據(jù)時(shí),可以使用POST或者GET方法
如果請(qǐng)求不改變服務(wù)器狀態(tài)指示返回?cái)?shù)據(jù),應(yīng)該使用GET。GET請(qǐng)求會(huì)被緩存,如果多次提取相同的數(shù)據(jù)會(huì)提高性能
而當(dāng)URL和請(qǐng)求的參數(shù)長(zhǎng)度超過(guò)2048個(gè)字符的時(shí)候才使用POST提取數(shù)據(jù)
多部分XHR(MXHR)多部分XHR允許使用一個(gè)HTTP請(qǐng)求獲取多個(gè)資源,我們可以將資源打包成一個(gè)特定分隔符定界的大字符串,從服務(wù)器發(fā)送到客戶端,JavaScript處理這些大字符串,然后根據(jù)它自身的類型和信息解析出每個(gè)資源
需要注意的是AJAX不會(huì)在瀏覽器中進(jìn)行緩存,自然使用MXHR也不會(huì)緩存,在一些靜態(tài)資源上使用這種方式其實(shí)并不太好。但是如果每次都確實(shí)需要去獲取,分多個(gè)請(qǐng)求發(fā)送會(huì)更慢。
IMG燈標(biāo)我們可以通過(guò)創(chuàng)建一個(gè)Image對(duì)象,將src設(shè)為一個(gè)腳本文件的URL,img元素我們并不需要插入到DOM中,這種形式稱為IMG燈標(biāo)
這種方式適用于GET請(qǐng)求,且服務(wù)器獲得數(shù)據(jù)后不必返回?cái)?shù)據(jù)給瀏覽器的情況
同時(shí)我們可以在Image的load事件中監(jiān)聽(tīng)服務(wù)端是否成功接受了數(shù)據(jù)
數(shù)據(jù)格式XML:支持廣泛但解析效率低,而且相當(dāng)冗長(zhǎng)
JSON: 小巧,輕便,解析速度較快
JSONP:使用JavaScript解釋器進(jìn)行解析,解析速度極快,數(shù)據(jù)量只比JSON多一點(diǎn)點(diǎn)(函數(shù)名稱和括號(hào))
HTML:無(wú)需解析,數(shù)據(jù)冗長(zhǎng)
自定義格式:自己解析,慢而易出錯(cuò),數(shù)據(jù)長(zhǎng)度可以很短
其他不要使用eval以及其類似
使用字面量
避免重復(fù)工作,檢測(cè)瀏覽器時(shí),保存首次檢測(cè)結(jié)果即可
考慮位操作
使用原聲方法,因?yàn)樗麄兪荂++寫(xiě)的
文件預(yù)處理,壓縮(gzip)、合并、uglify
嘗試CDN
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/49494.html
摘要:而像和會(huì)增加作用域鏈的長(zhǎng)度,所以也會(huì)降低性能。但是用獲取一些屬性時(shí),會(huì)不由自主地強(qiáng)迫隊(duì)列中的所有渲染事件前不完成。在條件增加時(shí),所帶來(lái)的性能負(fù)擔(dān)要高于,因此建議使用。它代價(jià)昂貴,且容易失控。 正巧看到在送書(shū),于是乎找了找自己博客上記錄過(guò)的一些東西來(lái)及其無(wú)恥的蹭書(shū)了~~~ 小廣告:更多內(nèi)容可以看我的博客 以下內(nèi)容均來(lái)自《高性能JavaScript》 JavaScript文件加載 ...
摘要:特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 特意對(duì)前端學(xué)習(xí)資源做一個(gè)匯總,方便自己學(xué)習(xí)查閱參考,和好友們共同進(jìn)步。 本以為自己收藏的站點(diǎn)多,可以很快搞定,沒(méi)想到一入?yún)R總深似海。還有很多不足&遺漏的地方,歡迎補(bǔ)充。有錯(cuò)誤的地方,還請(qǐng)斧正... 托管: welcome to git,歡迎交流,感謝star 有好友反應(yīng)和斧正,會(huì)及時(shí)更新,平時(shí)業(yè)務(wù)工作時(shí)也會(huì)不定期更...
摘要:端優(yōu)談?wù)勱P(guān)于前端的緩存的問(wèn)題我們都知道對(duì)頁(yè)面進(jìn)行緩存能夠有利于減少請(qǐng)求發(fā)送,從而達(dá)到對(duì)頁(yè)面的優(yōu)化。而作為一名有追求的前端,勢(shì)必要力所能及地優(yōu)化我們前端頁(yè)面的性能。這種方式主要解決了淺談前端中的過(guò)早優(yōu)化問(wèn)題過(guò)早優(yōu)化是萬(wàn)惡之源。 優(yōu)化向:?jiǎn)雾?yè)應(yīng)用多路由預(yù)渲染指南 Ajax 技術(shù)的出現(xiàn),讓我們的 Web 應(yīng)用能夠在不刷新的狀態(tài)下顯示不同頁(yè)面的內(nèi)容,這就是單頁(yè)應(yīng)用。在一個(gè)單頁(yè)應(yīng)用中,往往只有一...
摘要:是一個(gè)極度純凈的上傳插件,通過(guò)簡(jiǎn)單調(diào)整就可以融入到任何項(xiàng)目,支持多文件上傳上傳速率動(dòng)態(tài)控制真實(shí)進(jìn)度監(jiān)控分塊生成分塊上傳校驗(yàn)秒傳暫停取消等。 跨域?qū)W習(xí)筆記 前言: 當(dāng)一個(gè)資源,向與之所在服務(wù)器不同的域或端口請(qǐng)求另一個(gè)資源時(shí),這個(gè)HTTP請(qǐng)求,我們認(rèn)為是跨域的請(qǐng)求。出于安全考慮,瀏覽器會(huì)限制腳本發(fā)起的跨域HTTP請(qǐng)求。 那天后端讓我把token放到http請(qǐng)求頭字段里,說(shuō)是為了和RN端統(tǒng)一...
閱讀 1785·2021-11-15 11:37
閱讀 3056·2021-11-04 16:05
閱讀 1922·2021-10-27 14:18
閱讀 2755·2021-08-12 13:30
閱讀 2500·2019-08-29 14:18
閱讀 2086·2019-08-29 13:07
閱讀 2024·2019-08-27 10:54
閱讀 2726·2019-08-26 12:15