摘要:嵌套對象成員會造成重大性能影響盡量少用。一般來說你可以通過這種方法提高代碼的性能將經(jīng)常使用的對象成員數(shù)組項(xiàng)和域外變量存入局部變量中。在反復(fù)訪問的地方使用局部變量存放引用小心地處理集合因?yàn)樗麄儽憩F(xiàn)出存在性總是對底層文檔重新查詢。
前言
本期我來給大家推薦的書是《高性能JavaScript》,在這本書中我們能夠了解 javascript 開發(fā)過程中的性能瓶頸,如何提升各方面的性能,包括代碼的加載、運(yùn)行、DOM交互、頁面生存周期等。同樣我們今天還是用思維導(dǎo)圖的方式來精讀一遍。(思維導(dǎo)圖圖片可能有點(diǎn)小,記得點(diǎn)開看,你會有所收獲)
加載和執(zhí)行
管理瀏覽器中的 JavaScript 代碼是個棘手的問題,因?yàn)榇a執(zhí)行阻塞了其他瀏覽器處理過程,諸如用戶 界面繪制。每次遇到標(biāo)簽,頁面必須停下來等待代碼下載(如果是外部的)并執(zhí)行,然后再繼續(xù)處 理頁面其他部分。但是,有幾種方法可以減少 JavaScript 對性能的影響:
將所有標(biāo)簽放置在頁面的底部,緊靠 body 關(guān)閉標(biāo)簽
的上方。此法可以保證頁面在腳本 運(yùn)行之前完成解析。
將腳本成組打包。頁面的標(biāo)簽越少,頁面的加載速度就越快,響應(yīng)也更加迅速。不論外部腳本 文件還是內(nèi)聯(lián)代碼都是如此。
有幾種方法可以使用非阻塞方式下載 JavaScript:
為標(biāo)簽添加 defer 屬性(只適用于 Internet Explorer 和 Firefox 3.5 以上版本)
動態(tài)創(chuàng)建元素,用它下載并執(zhí)行代碼
用 XHR 對象下載代碼,并注入到頁面中
通過使用上述策略,你可以極大提高那些大量使用 JavaScript 代碼的網(wǎng)頁應(yīng)用的實(shí)際性能。
數(shù)據(jù)存取在 JavaScript 中,數(shù)據(jù)存儲位置可以對代碼整體性能產(chǎn)生重要影響。有四種數(shù)據(jù)訪問類型:直接量,變 量,數(shù)組項(xiàng),對象成員。它們有不同的性能考慮。
直接量和局部變量訪問速度非常快,數(shù)組項(xiàng)和對象成員需要更長時間。局部變量比域外變量快,因?yàn)樗挥谧饔糜蜴湹牡谝粋€對象中。變量在作用域鏈中的位置越深,訪問所需 的時間就越長。全局變量總是最慢的,因?yàn)樗鼈兛偸俏挥谧饔糜蜴湹淖詈笠画h(huán)。避免使用 with 表達(dá)式,因?yàn)樗淖兞诉\(yùn)行期上下文的作用域鏈。而且應(yīng)當(dāng)小心對待 try-catch 表達(dá)式的 catch 子句,因?yàn)樗哂型瑯有ЧG短讓ο蟪蓡T會造成重大性能影響,盡量少用。
一個屬性或方法在原形鏈中的位置越深,訪問它的速度就越慢。一般來說,你可以通過這種方法提高 JavaScript 代碼的性能:將經(jīng)常使用的對象成員,數(shù)組項(xiàng),和域外變 量存入局部變量中。然后,訪問局部變量的速度會快于那些原始變量。通過使用這些策略,你可以極大地提高那些需要大量 JavaScript 代碼的網(wǎng)頁應(yīng)用的實(shí)際性能。
DOM 編程
DOM 訪問和操作是現(xiàn)代網(wǎng)頁應(yīng)用中很重要的一部分。但每次你通過橋梁從 ECMAScript 島到達(dá) DOM 島 時,都會被收取“過橋費(fèi)”。為減少 DOM 編程中的性能損失,請牢記以下幾點(diǎn):
最小化 DOM 訪問,在 JavaScript 端做盡可能多的事情。在反復(fù)訪問的地方使用局部變量存放 DOM 引用.小心地處理 HTML 集合,因?yàn)樗麄儽憩F(xiàn)出“存在性”,總是對底層文檔重新查詢。將集合的 length 屬性緩 存到一個變量中,在迭代中使用這個變量。如果經(jīng)常操作這個集合,可以將集合拷貝到數(shù)組中。
如果可能的話,使用速度更快的 API,諸如 querySelectorAll()和 firstElementChild。注意重繪和重排版;批量修改風(fēng)格,離線操作 DOM 樹,緩存并減少對布局信息的訪問。動畫中使用絕對坐標(biāo),使用拖放代理。使用事件托管技術(shù)最小化事件句柄數(shù)量。
算法和流程控制
正如其他編程語言,代碼的寫法和算法選用影響 JavaScript 的運(yùn)行時間。與其他編程語言不同的是, JavaScript 可用資源有限,所以優(yōu)化技術(shù)更為重要。
for,while,do-while 循環(huán)的性能特性相似,誰也不比誰更快或更慢。除非你要迭代遍歷一個屬性未知的對象,否則不要使用 for-in 循環(huán)。改善循環(huán)性能的最好辦法是減少每次迭代中的運(yùn)算量,并減少循環(huán)迭代次數(shù)。
一般來說,switch 總是比 if-else 更快,但并不總是最好的解決方法。當(dāng)判斷條件較多時,查表法比 if-else 或者 switch 更快。
瀏覽器的調(diào)用棧尺寸限制了遞歸算法在 JavaScript 中的應(yīng)用;棧溢出錯誤導(dǎo)致其他代碼也不能正常執(zhí)行。如果你遇到一個棧溢出錯誤,將方法修改為一個迭代算法或者使用制表法可以避免重復(fù)工作。
運(yùn)行的代碼總量越大,使用這些策略所帶來的性能提升就越明顯。
字符串和正則表達(dá)式
密集的字符串操作和粗淺地編寫正則表達(dá)式可能是主要性能障礙,但本章中的建議可幫助您避免常見缺陷。當(dāng)連接數(shù)量巨大或尺寸巨大的字符串時,數(shù)組聯(lián)合是 IE7 和它的早期版本上唯一具有合理性能的方法。如果你不關(guān)心 IE7 和它的早期版本,數(shù)組聯(lián)合是連接字符串最慢的方法之一。使用簡單的+和+=取而代之, 可避免(產(chǎn)生)不必要的中間字符串。
回溯既是正則表達(dá)式匹配功能基本的組成部分,又是正則表達(dá)式影響效率的常見原因。回溯失控發(fā)生在正則表達(dá)式本應(yīng)很快發(fā)現(xiàn)匹配的地方,因?yàn)槟承┨厥獾钠ヅ渥址畡幼?導(dǎo)致運(yùn)行緩慢 甚至瀏覽器崩潰。避免此問題的技術(shù)包括:使相鄰字元互斥,避免嵌套量詞對一個字符串的相同部分多次 匹配,通過重復(fù)利用前瞻操作的原子特性去除不必要的回溯。
提高正則表達(dá)式效率的各種技術(shù)手段,幫助正則表達(dá)式更快地找到匹配,以及在非匹配位置上花費(fèi)更少 時間(見《更多提高正則表達(dá)式效率的方法》)。正則表達(dá)式并不總是完成工作的最佳工具,尤其當(dāng)你只是搜索一個文本字符串時。
雖然有很多方法來修整一個字符串,使用兩個簡單的正則表達(dá)式(一個用于去除頭部空格,另一個用于 去除尾部空格)提供了一個簡潔、跨瀏覽器的方法,適用于不同內(nèi)容和長度的字符串。從字符串末尾開始 循環(huán)查找第一個非空格字符,或者在一個混合應(yīng)用中將此技術(shù)與正則表達(dá)式結(jié)合起來,提供了一個很好的 替代方案,它很少受到字符串整體長度的影響。
快速響應(yīng)用戶界面
JavaScript 和用戶界面更新在同一個進(jìn)程內(nèi)運(yùn)行,同一時刻只有其中一個可以運(yùn)行。這意味著當(dāng) JavaScript 代碼正在運(yùn)行時,用戶界面不能響應(yīng)輸入,反之亦然。有效地管理 UI 線程就是要確保 JavaScript 不能運(yùn)行 太長時間,以免影響用戶體驗(yàn)。最后,請牢記如下幾點(diǎn):
JavaScript 運(yùn)行時間不應(yīng)該超過 100 毫秒。過長的運(yùn)行時間導(dǎo)致 UI 更新出現(xiàn)可察覺的延遲,從而對整體 用戶體驗(yàn)產(chǎn)生負(fù)面影響。
JavaScript 運(yùn)行期間,瀏覽器響應(yīng)用戶交互的行為存在差異。無論如何,JavaScript 長時間運(yùn)行將導(dǎo)致用 戶體驗(yàn)混亂和脫節(jié)。
定時器可用于安排代碼推遲執(zhí)行,它使得你可以將長運(yùn)行腳本分解成一系列較小的任務(wù)。
網(wǎng)頁工人線程是新式瀏覽器才支持的特性,它允許你在 UI 線程之外運(yùn)行 JavaScript 代碼而避免鎖定 UI。網(wǎng)頁應(yīng)用程序越復(fù)雜,積極主動地管理 UI 線程就越顯得重要。沒有什么 JavaScript 代碼可以重要到允 許影響用戶體驗(yàn)的程度。
Ajax
高性能 Ajax 包括:知道你項(xiàng)目的具體需求,選擇正確的數(shù)據(jù)格式和與之相配的傳輸技術(shù)。
作為數(shù)據(jù)格式,純文本和 HTML 是高度限制的,但它們可節(jié)省客戶端的 CPU 周期。XML 被廣泛應(yīng)用 普遍支持,但它非常冗長且解析緩慢。JSON 是輕量級的,解析迅速(作為本地代碼而不是字符串),交 互性與 XML 相當(dāng)。字符分隔的自定義格式非常輕量,在大量數(shù)據(jù)集解析時速度最快,但需要編寫額外的 程序在服務(wù)器端構(gòu)造格式,并在客戶端解析。
當(dāng)從頁面域請求數(shù)據(jù)時,XHR 提供最完善的控制和靈活性,盡管它將所有傳入數(shù)據(jù)視為一個字符串, 這有可能降低解析速度。另一方面,動態(tài)腳本標(biāo)簽插入技術(shù)允許跨域請求和本地運(yùn)行 JavaScript 和 JSON, 雖然它的接口不夠安全,而且不能讀取信息頭或響應(yīng)報文代碼。多部分 XHR 可減少請求的數(shù)量,可在一次響應(yīng)中處理不同的文件類型,盡管它不能緩存收到的響應(yīng)報文。當(dāng)發(fā)送數(shù)據(jù)時,圖像燈標(biāo)是最簡單和最 有效的方法。XHR 也可用 POST 方法發(fā)送大量數(shù)據(jù)。
除這些格式和傳輸技術(shù)之外,還有一些準(zhǔn)則有助于進(jìn)一步提高 Ajax 的速度:
減少請求數(shù)量,可通過 JavaScript 和 CSS 文件打包,或者使用 MXHR。
縮短頁面的加載時間,在頁面其它內(nèi)容加載之后,使用 Ajax 獲取少量重要文件。
確保代碼錯誤不要直接顯示給用戶,并在服務(wù)器端處理錯誤。
學(xué)會何時使用一個健壯的 Ajax 庫,何時編寫自己的底層 Ajax 代碼。
Ajax 是提升你網(wǎng)站潛在性能之最大的改進(jìn)區(qū)域之一,因?yàn)楹芏嗑W(wǎng)站大量使用異步請求,又因?yàn)樗峁?了許多不相關(guān)問題的解決方案,這些問題諸如,需要加載太多資源。對 XHR 的創(chuàng)造性應(yīng)用是如此的與眾 不同,它不是呆滯不友好的界面,而是響應(yīng)迅速且高效的代名詞;它不會引起用戶的憎恨,誰見了它都會 愛上它。
編程實(shí)踐JavaScript 提出了一些獨(dú)特的性能挑戰(zhàn),關(guān)系到你組織代碼的方法。網(wǎng)頁應(yīng)用變得越來越高級,包含的 JavaScript 代碼越來越多,出現(xiàn)了一些模式和反模式。請牢記以下編程經(jīng)驗(yàn):
通過避免使用 eval_r()和 Function()構(gòu)造器避免二次評估。此外,給 setTimeout()和 setInterval()傳遞函數(shù)參 數(shù)而不是字符串參數(shù)。
創(chuàng)建新對象和數(shù)組時使用對象直接量和數(shù)組直接量。它們比非直接量形式創(chuàng)建和初始化更快。
避免重復(fù)進(jìn)行相同工作。當(dāng)需要檢測瀏覽器時,使用延遲加載或條件預(yù)加載。
當(dāng)執(zhí)行數(shù)學(xué)遠(yuǎn)算時,考慮使用位操作,它直接在數(shù)字底層進(jìn)行操作。
原生方法總是比 JavaScript 寫的東西要快。盡量使用原生方法。
構(gòu)建并部署高性能 javascript 應(yīng)用開發(fā)和部署過程對基于 JavaScript 的應(yīng)用程序可以產(chǎn)生巨大影響,最重要的幾個步驟如下:
合并 JavaScript 文件,減少 HTTP 請求的數(shù)量
使用 YUI 壓縮器緊湊處理 JavaScript 文件
以壓縮形式提供 JavaScript 文件(gzip 編碼)
通過設(shè)置 HTTP 響應(yīng)報文頭使 JavaScript 文件可緩存,通過向文件名附加時間戳解決緩存問題
使用內(nèi)容傳遞網(wǎng)絡(luò)(CDN)提供 JavaScript 文件,CDN 不僅可以提高性能,它還可以為你管理壓縮和緩 存
所有這些步驟應(yīng)當(dāng)自動完成,不論是使用公開的開發(fā)工具諸如 Apache Ant,還是使用自定義的開發(fā)工具 以實(shí)現(xiàn)特定需求。如果你使這些開發(fā)工具為你服務(wù),你可以極大改善那些大量使用 JavaScript 代碼的網(wǎng)頁 應(yīng)用或網(wǎng)站的性能。
工具當(dāng)網(wǎng)頁或應(yīng)用程序變慢時,分析網(wǎng)上傳來的資源,分析腳本的運(yùn)行性能,使你能夠集中精力在那些需要 努力優(yōu)化的地方。使用網(wǎng)絡(luò)分析器找出加載腳本和其它頁面資源的瓶頸所在,這有助于決定哪些腳本需要延遲加載,或者 進(jìn)行進(jìn)一步分析。傳統(tǒng)的智慧告訴我們應(yīng)盡量減少 HTTP 請求的數(shù)量,盡量延遲加載腳本以使頁面渲染速度更快,向用戶 提供更好的整體體驗(yàn)。使用性能分析器找出腳本運(yùn)行時速度慢的部分,檢查每個函數(shù)所花費(fèi)的時間,以及函數(shù)被調(diào)用的次數(shù), 通過調(diào)用棧自身提供的一些線索來找出哪些地方應(yīng)當(dāng)努力優(yōu)化。雖然花費(fèi)時間和調(diào)用次數(shù)通常是數(shù)據(jù)中最有價值的點(diǎn),還是應(yīng)當(dāng)仔細(xì)察看函數(shù)的調(diào)用過程,可能發(fā)現(xiàn)其 它優(yōu)化方法。這些工具在那些現(xiàn)代代碼所要運(yùn)行的編程環(huán)境中不再神秘。在開始優(yōu)化工作之前使用它們,確保開發(fā)時 間用在解決問題的刀刃上。
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://specialneedsforspecialkids.com/yun/96946.html
摘要:強(qiáng)制類型轉(zhuǎn)換本章介紹了的數(shù)據(jù)類型之間的轉(zhuǎn)換即強(qiáng)制類型轉(zhuǎn)換包括顯式和隱式。強(qiáng)制類型轉(zhuǎn)換常常為人詬病但實(shí)際上很多時候它們是非常有用的。隱式強(qiáng)制類型轉(zhuǎn)換則沒有那么明顯是其他操作的副作用。在處理強(qiáng)制類型轉(zhuǎn)換的時候要十分小心尤其是隱式強(qiáng)制類型轉(zhuǎn)換。 前言 《你不知道的 javascript》是一個前端學(xué)習(xí)必讀的系列,讓不求甚解的JavaScript開發(fā)者迎難而上,深入語言內(nèi)部,弄清楚JavaSc...
摘要:可以將耗時任務(wù)拆解出去,降低主線程的壓力,避免主線程無響應(yīng)。主線程接收發(fā)消息每個實(shí)例通過接收消息,通過發(fā)送消息。收發(fā)主線程消息和主線程代碼類似,在代碼中,也是接收消息,這個消息來自主線程或者其它。 1 引言 本周精讀的文章是 speedy-introduction-to-web-workers,是一篇 Web Workers 快速入門的文章,借精讀這篇文章的機(jī)會,談?wù)剬?Web Wor...
摘要:目前我們的業(yè)務(wù)項(xiàng)目采用的來進(jìn)行優(yōu)化和首屏性能提升。可變性需要讓開發(fā)人員降低開發(fā)時的基準(zhǔn)線,來保證每一個用戶的體驗(yàn)。對于路由的切分以及庫的引入來說,這一個原則至關(guān)重要。快速生成一份站點(diǎn)的性能審查報告。 The Cost Of JavaScript 2018 關(guān)于原文 原文是在Medium上面看到的,Chrome工程師Addy Osmani發(fā)布的一篇文章,這位的Medium上面的自我介紹里...
摘要:從社區(qū)和過往的經(jīng)驗(yàn)而言異步編程的難題已經(jīng)基本解決無論是通過事件還是通過模式或者流程控制庫。本章主要介紹了主流的幾種異步編程解決方案這是目前中主要使用的方案。最后因?yàn)槿藗兛偸橇?xí)慣性地以線性的方式進(jìn)行思考以致異步編程相對較為難以掌握。 前言 如果你想要深入學(xué)習(xí)Node,那你不能錯過《深入淺出Node.js》這本書,它從不同的視角介紹了 Node 內(nèi)在的特點(diǎn)和結(jié)構(gòu)。由首章Node 介紹為索引...
摘要:前端進(jìn)階進(jìn)階構(gòu)建項(xiàng)目一配置最佳實(shí)踐狀態(tài)管理之痛點(diǎn)分析與改良開發(fā)中所謂狀態(tài)淺析從時間旅行的烏托邦,看狀態(tài)管理的設(shè)計誤區(qū)使用更好地處理數(shù)據(jù)愛彼迎房源詳情頁中的性能優(yōu)化從零開始,在中構(gòu)建時間旅行式調(diào)試用輕松管理復(fù)雜狀態(tài)如何把業(yè)務(wù)邏輯這個故事講好和 前端進(jìn)階 webpack webpack進(jìn)階構(gòu)建項(xiàng)目(一) Webpack 4 配置最佳實(shí)踐 react Redux狀態(tài)管理之痛點(diǎn)、分析與...
閱讀 3016·2021-10-08 10:18
閱讀 732·2019-08-30 15:54
閱讀 1067·2019-08-29 18:43
閱讀 2441·2019-08-29 15:33
閱讀 1305·2019-08-29 15:29
閱讀 1604·2019-08-29 13:29
閱讀 1026·2019-08-26 13:46
閱讀 1701·2019-08-26 11:55