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