摘要:性能訪問(wèn)字面量和局部變量的速度是最快的,訪問(wèn)數(shù)組和對(duì)象成員相對(duì)較慢變量標(biāo)識(shí)符解析過(guò)程搜索執(zhí)行環(huán)境的作用域鏈,查找同名標(biāo)識(shí)符。建議將全局變量存儲(chǔ)到局部變量,加快讀寫(xiě)速度。優(yōu)化建議將常用的跨作用域變量存儲(chǔ)到局部變量,然后直接訪問(wèn)局部變量。
缺陷
這本書(shū)是2010年出版的,這本書(shū)談性能是有時(shí)效性的,現(xiàn)在馬上就2018年了,這幾年前端發(fā)展的速度是飛快的,書(shū)里面還有一些內(nèi)容考慮IE6、7、8的東西,殊不知現(xiàn)在這些都已經(jīng)不再考慮了,所以不可避免的有一些知識(shí)是比較老的。有些解決方法現(xiàn)在已經(jīng)不是最好的解決方式,比如工具那一章。
前言總的來(lái)說(shuō),這本書(shū)整體給出的性能優(yōu)化建議,以及作者耐心的實(shí)踐,對(duì)我們開(kāi)發(fā)優(yōu)化的啟發(fā)和幫助還是很大的,因?yàn)樗镞叺暮芏嘀R(shí),都是作者通過(guò)實(shí)踐總結(jié)出來(lái)的,都是經(jīng)驗(yàn)的積累,這在一般的教科書(shū)上是學(xué)不到的。特別是對(duì)于js基礎(chǔ)比較差一點(diǎn)的,里面有很多知識(shí)點(diǎn)盡管在現(xiàn)在還是非常有必要的。
下面我就將各章節(jié)的一些重要的知識(shí)點(diǎn)總結(jié)寫(xiě)出來(lái),爭(zhēng)取將干貨都提取出來(lái)。
本文首發(fā)于我的個(gè)人blog:obkoro1.com正文 第一章-加載和執(zhí)行
js的阻塞特性:
當(dāng)瀏覽器在執(zhí)行js代碼的時(shí)候,不能同時(shí)做其他事情。(界面ui線程和js線程用的是同一進(jìn)程,所以js執(zhí)行越久,網(wǎng)頁(yè)的響應(yīng)時(shí)間越長(zhǎng)。)
腳本的位置
如果把腳本放在中,頁(yè)面會(huì)等js文件全部下載并執(zhí)行完成后才開(kāi)始渲染,在這些文件下載和執(zhí)行的過(guò)程中:會(huì)導(dǎo)致訪問(wèn)網(wǎng)站的時(shí)候有明顯的延遲,表現(xiàn)為:頁(yè)面空白。
性能提升:推薦將所有的標(biāo)簽盡可能的放到標(biāo)簽的底部,優(yōu)先渲染頁(yè)面,減少頁(yè)面空白時(shí)間。
組件腳本。
每個(gè)標(biāo)簽初始下載的時(shí)候都會(huì)阻塞頁(yè)面的渲染。性能提升做法:
減少內(nèi)嵌腳本:減少內(nèi)嵌的標(biāo)簽,將代碼寫(xiě)在一個(gè)標(biāo)簽中。
合并外鏈的js文件:http請(qǐng)求會(huì)帶來(lái)額外的性能開(kāi)銷(xiāo),栗子:下載一個(gè)100KB的js文件比下載4個(gè)25kb的js文件更快。具體操作方法自行搜索。
無(wú)阻塞腳本的方法
script標(biāo)簽的aync屬性:
async 屬性規(guī)定一旦腳本可用,則會(huì)異步執(zhí)行。async 屬性僅適用于外部腳本(只有在使用 src 屬性時(shí))。如果 async="async":腳本相對(duì)于頁(yè)面的其余部分異步地執(zhí)行(當(dāng)頁(yè)面繼續(xù)進(jìn)行解析時(shí),腳本將被執(zhí)行)
script標(biāo)簽的defer屬性:
js文件在頁(yè)面解析到script標(biāo)簽的時(shí)候開(kāi)始下載,但并不會(huì)執(zhí)行,dom加載完成執(zhí)行。這兩個(gè)屬性的區(qū)別在于執(zhí)行時(shí)機(jī)。
動(dòng)態(tài)腳本元素。
js操作dom創(chuàng)建標(biāo)簽,自定義生成標(biāo)簽的type、src屬性。文件會(huì)在該元素被添加到頁(yè)面的時(shí)候開(kāi)始下載。ps:如果文件順序很重要的話,最好按照順序合成一個(gè)文件。然后再添加到頁(yè)面中。這樣:無(wú)論何時(shí)啟動(dòng)下載。文件的下載和執(zhí)行過(guò)程不會(huì)阻塞頁(yè)面的其他進(jìn)程。
用get請(qǐng)求一個(gè)文件,請(qǐng)求好了。然后創(chuàng)建動(dòng)態(tài)腳本,最后添加進(jìn)去。
缺陷:文件要再請(qǐng)求頁(yè)面的同一個(gè)域。不能從cdn下載
把文件放在body標(biāo)簽簽名,
合并腳本,減少標(biāo)簽。
采用無(wú)阻塞下載js。使用script的defer和async屬性 異步下載。動(dòng)態(tài)創(chuàng)建script標(biāo)簽和執(zhí)行代碼。
第二章-數(shù)據(jù)存取js四種基本的數(shù)據(jù)存取位置。
1、字面量:字符串、數(shù)字、布爾、對(duì)象、數(shù)組、函數(shù)、正則、null、undefined,字面量只代表自身,沒(méi)有存儲(chǔ)位置。 2、局部變量。 let var 聲明的變量。3、數(shù)組元素。4、對(duì)象成員。
性能:訪問(wèn)字面量和局部變量的速度是最快的,訪問(wèn)數(shù)組和對(duì)象成員相對(duì)較慢
變量標(biāo)識(shí)符解析過(guò)程:
搜索執(zhí)行環(huán)境的作用域鏈,查找同名標(biāo)識(shí)符。搜索過(guò)程從作用域鏈頭部開(kāi)始,也就是當(dāng)前運(yùn)行函數(shù)的活動(dòng)對(duì)象。如果找到,就使用這個(gè)標(biāo)識(shí)符,對(duì)應(yīng)的變量;如果沒(méi)有找到,繼續(xù)搜索下面的對(duì)象。搜索過(guò)程會(huì)持續(xù)進(jìn)行,直到找到標(biāo)識(shí)符,若無(wú)法搜索到匹配的對(duì)象,那么標(biāo)識(shí)符被視為未定義、
性能問(wèn)題:一個(gè)標(biāo)識(shí)符所在的位置越深,它的讀寫(xiě)速度也就越慢。因此,函數(shù)中讀寫(xiě)局部變量總是最快的,而讀寫(xiě)全局變量通常是最慢的。
建議:將全局變量存儲(chǔ)到局部變量,加快讀寫(xiě)速度。
閉包,原型,嵌套對(duì)象。
優(yōu)化建議:將常用的跨作用域變量存儲(chǔ)到局部變量,然后直接訪問(wèn)局部變量。理由如上,變量標(biāo)識(shí)符解析過(guò)程。
第二章數(shù)據(jù)存取小結(jié):訪問(wèn)字面量和局部變量的速度最快,相反,訪問(wèn)數(shù)組元素和對(duì)象成員相對(duì)較慢。
由于局部變量存在于作用域鏈的起始位置,因?yàn)?strong>訪問(wèn)局部變量比訪問(wèn)跨作用域變量更快。這個(gè)道理同樣適用于數(shù)組,對(duì)象,跨作用域變量。
把常用的對(duì)象,數(shù)組,跨域變量保存在局部變量可以改善js性能,局部變量訪問(wèn)速度更快。
第三章DOM編程小結(jié):dom操作天生就慢,盡量減少dom操作,減少訪問(wèn)dom的次數(shù)。
使用document.querySelect來(lái)做選擇器,比其他方式快。
需要多次訪問(wèn)某個(gè)dom節(jié)點(diǎn),使用局部變量存儲(chǔ)。
html集合,把集合長(zhǎng)度緩存到一個(gè)變量中,然后遍歷使用這個(gè)變量,如果經(jīng)常操作集合,建議拷到一個(gè)數(shù)組中。
要留意瀏覽器的重繪和重排;批量修改樣式的時(shí)候,‘離線’操作DOM樹(shù),使用緩存,并減少訪問(wèn)布局信息的次數(shù)。
重繪和重排是DOM編程優(yōu)化的一個(gè)相當(dāng)重要概念:重繪和重排。
動(dòng)畫(huà)中使用絕對(duì)定義,使用拖放處理。
使用事件委托來(lái)減少事件處理器的數(shù)量。
第四章算法和流程控制小結(jié):for、while和do-while循環(huán)性能差不多,for-in循環(huán)速度只有前面幾種類型的1/7,所以盡量避免使用for-in循環(huán),除非你需要遍歷一個(gè)屬性數(shù)量未知的對(duì)象。
forEach比f(wàn)or慢,如果運(yùn)行速度要求嚴(yán)格,不建議使用。
改善循環(huán)性能的最佳方式是減少每次迭代的工作量和減少循環(huán)迭代的次數(shù)。
減少迭代工作量:減少屬性查找和倒序循環(huán),循環(huán)次數(shù)越多,性能優(yōu)化越明顯。
for(var i=0;i0的時(shí)候會(huì)自動(dòng)轉(zhuǎn)換為true,等于0的時(shí)候?yàn)閒alse。 //倒序循環(huán):控制條件從(迭代數(shù)少于總數(shù)嗎?它是否為true?)變?yōu)椋ㄋ欠駷閠rue)
減少迭代的次數(shù):"Duff"s Device"循環(huán)體展開(kāi)技術(shù),有興趣的可以看一下,迭代工作量大于1000的時(shí)候適用。
if-else與switch:條件數(shù)量越大,越傾向于使用switch。
優(yōu)化if-else:
1、把最可能出現(xiàn)的條件放在首位。2、使用二分法把值域分成一系列的區(qū)間。
瀏覽器的調(diào)用棧大小限制了遞歸算法在js中的應(yīng)用;棧溢出錯(cuò)誤會(huì)導(dǎo)致其他代碼中斷運(yùn)行。
小心使用遞歸,現(xiàn)在es6遞歸可以尾遞歸,在es6中只要使用尾遞歸就不會(huì)發(fā)生棧溢出,相對(duì)節(jié)省性能。第五章字符串和正則表達(dá)式小結(jié):
字符串合并的時(shí)候使用簡(jiǎn)單的"+"和"+="操作符。
str+="abc"+"efg;//2個(gè)以上的字符串拼接,會(huì)產(chǎn)生臨時(shí)字符串 str=str+"abc"+"efg";//推薦,提速10%~40%
書(shū)里面講的正則原理和回溯原理,這個(gè)很重要,找個(gè)篇博客:跟書(shū)里面講的差不多,但還是建議大家可以去找找PDF好好看看正則表達(dá)式這節(jié)。
提高正則表達(dá)式效率的方法:
1、最重要的是:具體化正則表達(dá)式!具體化正則表達(dá)式!具體化正則表達(dá)式! 2、關(guān)注如何讓匹配更快失敗,找出一些必需,特殊的字符 3、正則表達(dá)式以簡(jiǎn)單的、必需的字元開(kāi)始。 4、使用量詞模式,使它們后面的字元互斥。 5、較少分支數(shù)量,縮小分支范圍 6、使用合適的量詞 7、把正則表達(dá)式賦值給變量并重用 8、將復(fù)雜的正則拆分為簡(jiǎn)單的片段 //事實(shí)上,書(shū)里面講的方法不止這么幾個(gè),而且每一個(gè)都有詳細(xì)的解析 大佬們 還是去看看這一章節(jié)吧
正則表達(dá)式并不總是最好的解決方案,當(dāng)你只是搜索字面字符串或者你事先知道字符串的哪一部分將要被查找時(shí):
使用indexOf()和lastIndexOf()更適合查找特定字符串的位置或者判斷它們是否存在 //例如:判斷當(dāng)前瀏覽器之類。第六章快速響應(yīng)的用戶界面小結(jié):
js和用戶界面更新在同一個(gè)進(jìn)程中運(yùn)行,因此一次只能處理一件事情。高效的管理UI線程就是要確保js不能運(yùn)行太長(zhǎng)時(shí)間,以免影響用戶體驗(yàn)。
瀏覽器限制了js任務(wù)的運(yùn)行時(shí)間,這種限制很有必要,它確保某些惡意代碼不能通過(guò)永不停止的密集操作鎖住用戶的瀏覽器。此限制分為兩種:調(diào)用棧的大小和長(zhǎng)時(shí)間運(yùn)行腳本。
任何js任務(wù)都不應(yīng)當(dāng)執(zhí)行超過(guò)100毫秒。過(guò)長(zhǎng)的運(yùn)行時(shí)間會(huì)導(dǎo)致UI更新出現(xiàn)明顯延遲,從而對(duì)用戶體驗(yàn)造成負(fù)面影響。
定時(shí)器可用來(lái)安排代碼延遲執(zhí)行,它使得你可以把長(zhǎng)時(shí)間運(yùn)行腳本分解成一系列的小任務(wù)。
第七章 AJAX 小結(jié)這一章節(jié)貌似東西都比較老一點(diǎn)。。
post更適合發(fā)送大量數(shù)據(jù)到服務(wù)器。
get請(qǐng)求能夠被瀏覽器緩存,Expires頭信息設(shè)置瀏覽器緩存請(qǐng)求多久。可用于從不改變的圖片或者其他靜態(tài)數(shù)據(jù)集(js、css等)
JSON是一種使用js對(duì)象和數(shù)組直接量編寫(xiě)的輕量級(jí)且易于解析的數(shù)據(jù)格式,它不僅傳輸尺寸小,而且解析速度快。JSON是高性能AJAX的基礎(chǔ),尤其在使用動(dòng)態(tài)腳本注入時(shí)。
json應(yīng)該是近幾年一直在用的。。。
減少請(qǐng)求數(shù),通過(guò)合并js和css文件。
縮短頁(yè)面的加載時(shí)間,頁(yè)面主要內(nèi)容加載完成后,用AJAX獲取那些次要的文件。
第八章編程實(shí)踐小結(jié)避免雙重求值:避免使用eval()和 function()構(gòu)造器來(lái)避免雙重求值帶來(lái)的性能消耗,同樣的,給setTimeout()和setInterval()傳遞函數(shù)而不是字符串作為參數(shù)。
//雙重求值:就是在js代碼中執(zhí)行另一段js代碼,不建議使用下面這些方式
eval("代碼")
function構(gòu)造函數(shù)--new function("代碼")
setTimeout(‘代碼’,100)和setInterval(‘代碼’,100)
盡量使用直接量創(chuàng)建對(duì)象和數(shù)組。直接量的創(chuàng)建和初始化都比非直接量形式要快。
避免做重復(fù)工作,能節(jié)省的步驟就節(jié)省。
js原生方法總會(huì)比你寫(xiě)的任何代碼都要快。
第九章 構(gòu)建并部署高性能js應(yīng)用小結(jié)構(gòu)建和部署的過(guò)程對(duì)基于js的web應(yīng)用的性能有著巨大影響。這個(gè)過(guò)程中最重要的步驟有:
合并、壓縮js文件。可使用Gzip壓縮,能夠減少約70%的體積!
這些都是在構(gòu)建過(guò)程中完成的工作,不要等到運(yùn)行時(shí)去做,webpack也是在構(gòu)建過(guò)程中,完成的工作。
通過(guò)正確設(shè)置HTTP響應(yīng)頭來(lái)緩存js文件,通過(guò)向文件名增加時(shí)間戳來(lái)避免緩存問(wèn)題。
使用CDN提供js文件;CDN不僅可以提升性能,它也為你管理文件的壓縮與緩存,。
第十章 工具 小結(jié):當(dāng)網(wǎng)頁(yè)變慢時(shí),分析從網(wǎng)絡(luò)下載的資源以及分析的資源以及分析腳本的運(yùn)行性能能讓你專注于那些最需要優(yōu)化的地方。
使用網(wǎng)絡(luò)分析工具找出加載腳本和頁(yè)面中其他資源的瓶頸,這會(huì)幫助你決定那些腳本需要延遲加載,或者需要進(jìn)一步分析。
檢查圖片、樣式表和腳本的加載過(guò)程,以及它們對(duì)頁(yè)面整體加載和渲染的影響。從而針對(duì)性的做出優(yōu)化
把腳本盡可能延遲加載,這樣做可以加快頁(yè)面渲染速度,給用戶帶來(lái)更好的體驗(yàn)。
確認(rèn)腳本和其他資源文件的加載過(guò)程已經(jīng)被優(yōu)化
這里主要是說(shuō)文件從服務(wù)器的下載速度,比如服務(wù)器那邊的配置問(wèn)題之類的。
栗子:我就被后端坑過(guò)。一個(gè)js文件就200k ,下載下來(lái)需要50秒鐘!
后面發(fā)現(xiàn)原來(lái)是后端那邊nginx沒(méi)有開(kāi)啟加速配置什么的,導(dǎo)致出現(xiàn)的問(wèn)題,找問(wèn)題找半天。
測(cè)試腳本的運(yùn)行時(shí)間,用一個(gè)Date實(shí)例減去另一個(gè)Date實(shí)例,得到的時(shí)間差就是腳本運(yùn)行消耗的時(shí)間。
let start=new Date();
//你的代碼
let time=newDate()-start;
chrome ,火狐 等主流瀏覽器的控制面板,已經(jīng)能夠反映很多性能問(wèn)題。仔細(xì)分析就能找出很多問(wèn)題。例如:資源加載,斷點(diǎn)等
后話事實(shí)上,自認(rèn)為這本書(shū)最寶貴的就是一些提到的細(xì)節(jié),比如:
1、字符串合并的時(shí)候使用簡(jiǎn)單的"+"和"+="操作符。
str+="abc"+"efg;//2個(gè)以上的字符串拼接,會(huì)產(chǎn)生臨時(shí)字符串 str=str+"abc"+"efg";//推薦,提速10%~40%
2、避免雙重求值:避免使用eval()和 function()構(gòu)造器來(lái)避免雙重求值帶來(lái)的性能消耗,同樣的,給setTimeout()和setInterval()傳遞函數(shù)而不是字符串作為參數(shù)。
//雙重求值:就是在js代碼中執(zhí)行另一段js代碼,不建議使用下面這些方式 eval("代碼") function構(gòu)造函數(shù)--new function("代碼") setTimeout(‘代碼’,100)和setInterval(‘代碼’,100)這些東西可以讓我們知道什么是更好的實(shí)踐,什么樣的代碼可以跑得更快,讓我們養(yǎng)成更好的開(kāi)發(fā)習(xí)慣。
書(shū)不太厚,如果對(duì)里面的內(nèi)容感興趣,還是建議買(mǎi)一本回家看一看。
以上2017.1.9
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/92535.html
摘要:局部變量位于作用域鏈的起始位置,因此訪問(wèn)速度最快全局變量位于作用域鏈的最末端,因此訪問(wèn)速度最慢。如訪問(wèn)時(shí)間實(shí)例屬性第一層原型屬性第二層原型屬性在同一個(gè)函數(shù)中沒(méi)必要多次讀取同一個(gè)對(duì)象成員,建議第一次查詢到值后就將其存儲(chǔ)在局部變量中。 javascript中有四種基本的數(shù)據(jù)存取位置:字面量、變量、數(shù)組元素、對(duì)象成員。 1.訪問(wèn)字面量和局部變量的速度最快,訪問(wèn)數(shù)組元素和對(duì)象成員相對(duì)較慢。 2...
摘要:除此以外,讓元素脫離文檔流也是一個(gè)很好的方法。因?yàn)樵匾坏┟撾x文檔流,它對(duì)其他元素的影響幾乎為零,性能的損耗就能夠有效局限于一個(gè)較小的范圍。講完重排與重繪,往元素上綁定事件也是引起性能問(wèn)題的元兇。高性能這本書(shū)非常精致,內(nèi)容也非常豐富。 showImg(https://segmentfault.com/img/bVJgbt?w=600&h=784); 入手《高性能JavaScript》一...
摘要:設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐讀書(shū)筆記最近利用碎片時(shí)間在上面閱讀設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐讀書(shū)這本書(shū),剛開(kāi)始閱讀前兩章內(nèi)容,和大家分享下我覺(jué)得可以在項(xiàng)目中用的上的一些筆記。事件綁定暫時(shí)這么多,以后會(huì)不定期更新一些關(guān)于我讀這本書(shū)的筆記內(nèi)容 JavaScript 設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐讀書(shū)筆記 最近利用碎片時(shí)間在 Kindle 上面閱讀《JavaScript 設(shè)計(jì)模式與開(kāi)發(fā)實(shí)踐讀書(shū)》這本書(shū),剛開(kāi)始閱讀前兩章內(nèi)容,...
摘要:作用域鏈查找作用域鏈的查找是逐層向上查找。而全局變量和閉包則會(huì)與之相反,繼續(xù)保存,所以使用用后需手動(dòng)標(biāo)記清除,以免造成內(nèi)存泄漏。獲取元素的屬性獲取元素的屬性等參考文檔高級(jí)程序設(shè)計(jì)作者以樂(lè)之名本文原創(chuàng),有不當(dāng)?shù)牡胤綒g迎指出。 showImg(https://segmentfault.com/img/bVburXV?w=500&h=399); 作用域鏈查找 作用域鏈的查找是逐層向上查找。查...
摘要:包括元素的高度上下內(nèi)邊距上下邊框值,如果元素的的值為那么該值為。該值為元素的包含元素。最后,所有這些偏移量都是只讀的,而且每次訪問(wèn)他們都需要重新計(jì)算。為了避免重復(fù)計(jì)算,可以將計(jì)算的值保存起來(lái),以提高性能。 offsetHeight 包括元素的高度、上下內(nèi)邊距、上下邊框值,如果元素的style.display的值為none,那么該值為0。offsetWidth 包括元素的寬度、左...
摘要:設(shè)定瀏覽器屬性的屬性的方法叫做駝峰式命名是函數(shù)名方法名和對(duì)象屬性名的命名首選格式。由瀏覽器預(yù)先定義的對(duì)象被稱為宿主對(duì)象。在給某個(gè)元素添加了事件處理函數(shù)后,一旦事件發(fā)生,相應(yīng)的代碼就會(huì)執(zhí)行。 1.JavaScript是一個(gè)使網(wǎng)頁(yè)具有交互能力的程序設(shè)計(jì)語(yǔ)言。 2.設(shè)定瀏覽器屬性的屬性的方法叫做BOM. 3.駝峰式命名(myMood)是函數(shù)名、方法名和對(duì)象屬性名的命名首選格式。 4.命名變量...
閱讀 3104·2021-09-24 10:26
閱讀 3277·2021-09-23 11:54
閱讀 4697·2021-09-22 15:33
閱讀 2256·2021-09-09 09:33
閱讀 1662·2021-09-07 10:10
閱讀 965·2019-08-30 11:09
閱讀 2854·2019-08-29 17:13
閱讀 1011·2019-08-29 12:35