摘要:然后執(zhí)行環(huán)境會創(chuàng)建一個活動對象,活動對象作為函數(shù)運行的變量對象,包含所有局部變量命名參數(shù)參數(shù)集合和,當(dāng)執(zhí)行環(huán)境銷毀,活動對象也被銷毀。
高性能JavaScript整理總結(jié)
關(guān)于前端性能優(yōu)化:首先想到的是雅虎軍規(guī)34條
然后最近看了《高性能JavaScript》
大概的把書中提到大部分知識梳理了下并加上部分個人理解
這本書有參考雅虎特別性能小組的研究成果,所以跟34 軍規(guī)有很多相似之處
有不當(dāng)之處請在評論區(qū)指正,感謝~
約定:很多單詞語法都是簡寫比如doc指document,點點點代表不重要代碼省略,碼字不易(/雙手合十)
1. 加載和執(zhí)行JavaScript是單線程,所以JavaScript的加載和執(zhí)行是從上至下加載執(zhí)行完一個再繼續(xù)加載執(zhí)行下一個文件,會阻塞頁面資源的加載,所以一般情況下JavaScript文件放在body標(biāo)簽內(nèi)底部,很多后端開發(fā)人員放在body標(biāo)簽外下面,這樣做不好的地方有兩處:1、不規(guī)范 2、可能會造成js獲取不到頁面元素而導(dǎo)致報錯。而放在body標(biāo)簽內(nèi)底部可以確保js執(zhí)行前頁面渲染完成
js... //正確 js... //錯誤
合并腳本,每個
三種無阻塞下載JavaScript的方法:
1.使用
閉包的[[scope]]屬性引用了assignEvents執(zhí)行環(huán)境作用域鏈的對象(這個對象包含id屬性),當(dāng)執(zhí)行結(jié)束時,執(zhí)行環(huán)境銷毀,理應(yīng)活動對象也被銷毀,但是因為閉包的引入,導(dǎo)致這個活動對象處于激活狀態(tài),就無法銷毀,這就需要更多的內(nèi)存空間。
由于IE使用非原生JavaScript對象實現(xiàn)DOM對象,所以閉包可能導(dǎo)致內(nèi)存泄漏。
由于saveDom方法跨作用域訪問量變量id,所以閉包會帶來性能消耗,解決辦法是:常用的跨作用域變量存儲在局部變量中使用
對象成員
大部分JavaScript代碼是面向?qū)ο缶帉懙模ㄗ远x對象、BOM/DOM),所以會導(dǎo)致非常頻繁的訪問對象成員。所以訪問對象也有可優(yōu)化的地方
嵌套成員:對象可以嵌套其他成員
嵌套深度與讀取時間成正比
原型鏈
推薦一個回答,第一個 蘇墨橘的回答,相比于之前看的千篇一律的解答,這個更容易理解
關(guān)于原型鏈
三個問題:
1.訪問和修改DOM元素
2.修改DOM元素樣式導(dǎo)致的重繪和重排
3.通過DOM事件處理與用戶交互
DOM
DOM:document object module 文檔對象模型,可以理解為操作文檔的程序接口
為什么說DOM慢,操作DOM代價昂貴,簡單理解就是兩個獨立的功能只要通過接口彼此連接,就會產(chǎn)生消耗。比如:中國人買iPhone,美國人買衛(wèi)龍,需要交稅的,這個稅就是消耗,同樣,從DOM到JavaScript或從JavaScript到DOM都有類似的消耗。
所以盡量的減少這種交稅的次數(shù)來達(dá)到一定的性能優(yōu)化,
最壞的方式就是在循環(huán)中操作或者訪問DOM,非常消耗性能。
//bad for(var i = 0; i < 10000; i++){ document.querySelectorAll("#aaa").innerHTML += "a"; } //good var aaaHtml = ""; for(var i = 0; i < 10000; i++){ aaaHtml += "a"; } document.querySelectorAll("#aaa").innerHTML += aaaHtml;
關(guān)于innerHTML和DOM方法(doc.createElement())誰更快
不考慮Web標(biāo)準(zhǔn)的情況下,差不多。
除了最新版的WebKit內(nèi)核之外的瀏覽器中,innerHTML更快,舊版本瀏覽器效率更高
新版的WebKit內(nèi)核的瀏覽器DOM方法更快
克隆節(jié)點帶來的優(yōu)化效果不是很明顯、略過
訪問集合元素時使用局部變量(跟操作一個元素多次是一個道理,不贅述)
遍歷DOM
一般來說,querySelectorAll()是獲取元素最快的API 返回的是一個NodeList
querySelector() 返回的是element,
querySelectorAll()還有一點就是可以同時獲取兩類元素
var two = doc.querySelectorAll("div.aaa,div.bbb");
重繪和重排
瀏覽器下載完頁面中的所有組件--HTML標(biāo)記、JavaScript、CSS、圖片之后會解析生成兩個內(nèi)部數(shù)據(jù)結(jié)構(gòu):
1.DOM樹 表示頁面結(jié)構(gòu) 比如操場上早操,小紅你站這,小綠你站那,小明...(滾出去),哈,開個玩笑,這種位置的結(jié)構(gòu)就像DOM樹
2.渲染樹
表示DOM節(jié)點如何顯示 比如 小紅穿綠衣服,小綠穿紅衣服,小明穿毛呢大衣 小紅長頭發(fā) 小綠綠頭發(fā)等等
DOM樹中每一個需要顯示的節(jié)點在渲染樹種至少存在一個對應(yīng)的節(jié)點(隱藏元素沒有對應(yīng)節(jié)點,所以可以利用這一點,先把元素隱藏然后處理然后顯示來優(yōu)化消耗的性能),渲染樹中的節(jié)點被稱為‘幀’或者‘盒’,符合CSS模型定義。(盒子模型不是落地成盒)當(dāng)DOM和渲染樹構(gòu)建完成,瀏覽器開始顯示頁面元素。
那什么時候開始重繪和重排呢:
當(dāng)DOM變化影響了幾何屬性,瀏覽器會讓渲染樹中受到影響的部分失效,重新構(gòu)造渲染樹。這個過程稱為重排; 比如班級座位正常,某段時間后小明狂胖200斤,本來小明坐一個位置,現(xiàn)在需要兩個位置,其他同學(xué)就需要往兩邊坐或者往后坐,當(dāng)然,小明會不會滾出去取決于小明的成績好壞。
完成重排后,,瀏覽器會把受影響的部分重新繪制到屏幕上,這個過程稱為重繪;
當(dāng)改變DOM的非幾何屬性時,只會發(fā)生重繪,不會重排;
重繪和重排都是代價昂貴;盡量減少
重排何時發(fā)生:
1.添加或刪除可見DOM元素
2.元素位置改變
3.元素尺寸改變(內(nèi)外邊距、邊框厚寬高等)
4.內(nèi)容改變 (內(nèi)容導(dǎo)致尺寸變化的時候)
5.頁面渲染器初始化
6.瀏覽器窗口尺寸變化
減少重繪和重排
//三次重繪 el.style.borderLeft = "1px"; el.style.borderRight = "2px"; el.style.padding = "5px"; //一次重繪 el.style.cssText = "border-left: 1px;border-right: 2px; padding: 5px";
批量修改DOM時如何減少重繪和重排: 步驟:
1.使元素脫離文檔流
2.對其應(yīng)用多重改變
3.把元素帶回文檔中 //步驟1 3 兩次重排
三種方法使DOM脫離文檔:
1.隱藏元素--應(yīng)用修改--顯示
2.使用文檔片斷,在當(dāng)前DOM之外構(gòu)建一個子樹,再拷回文檔
3.拷貝到一個脫離文檔的節(jié)點中,修改副本,副本替換原始元素
讓元素脫離動畫流
一般來說,重排只會影響一小部分渲染樹,但是也有可能影響很大一部分甚至全部。一次大規(guī)模的重排可能會讓用戶覺得頁面一頓一頓的,影響用戶體驗
避免大部分重排:元素使用絕對定位讓其脫離文檔流--動畫--恢復(fù)定位
IE和:hover
從IE7開始,IE可以在任何元素上使用:hover這個偽選擇器,但是當(dāng)你大量元素使用時 會降低響應(yīng)速度 IE8更明顯
事件委托:事件逐成冒泡被父級捕獲
每綁定一個事件處理器都是有代價的
事件三階段:捕獲--到達(dá)目標(biāo)--冒泡
事件委托的兼容性問題:訪問事件對象、判斷事件源、取消冒泡(可選)、阻止默認(rèn)動作(可選)
使用事件委托來減少事件處理器的數(shù)量
循環(huán)
大多數(shù)編程語言中,代碼執(zhí)行時間大部分消耗在循環(huán)中,所以循環(huán)也是提升性能的重要環(huán)節(jié)之一
JavaScript四種循環(huán):
1.for循環(huán)
Tips:for循環(huán)初始化會創(chuàng)建一個函數(shù)級變量而不是循環(huán)級,因為JavaScript只有函數(shù)級作用域(ES6存在塊級作用域if(){let n = ...}let定義的n只作用于if塊內(nèi)部,執(zhí)行完就會釋放不會導(dǎo)致變量提升),所以在for循環(huán)中定義一個變量和在循環(huán)體外定義一個變量時一樣的 var i = 100; for(var i = 0; i < 10; i++){ console.log(i) //0,1,2,3...9 }
2.while循環(huán)
3.do-while循環(huán)
4.for in 循環(huán)
Tips:for in循環(huán)可以枚舉任何對象的屬性名(不是值),但是for in比其他三個循環(huán)明顯要慢,所以除非要迭代一個屬性數(shù)量未知的對象,否則避免使用for in循環(huán),如果遍歷一個屬性數(shù)量已知屬性列表,其他循環(huán)比for in快,比如:
var arr = ["name","age"], i = 0; while(i < arr.length){ process(object[arr[i]]); }
假設(shè)以上四種循環(huán)類型性能一樣,可以從兩個方面去優(yōu)化循環(huán)的性能:
(當(dāng)循環(huán)體復(fù)雜度為X時,優(yōu)化方案優(yōu)先減少循環(huán)體的復(fù)雜度,循環(huán)體復(fù)雜度大于X時,優(yōu)化方案優(yōu)先減少迭代次數(shù) )
1.每次迭代的事務(wù)(減少循環(huán)體的復(fù)雜度)
2.迭代的次數(shù)(減少循環(huán)的次數(shù),百度‘達(dá)夫設(shè)備’),可以這么理解,達(dá)夫設(shè)備就是拆解循環(huán),比如遍歷一個長度為100的數(shù)組,普通情況下循環(huán)體執(zhí)行100次,達(dá)夫設(shè)備的思想是把100次拆為每次循環(huán)執(zhí)行多次(n表示)100對n取余,執(zhí)行取余次數(shù),再執(zhí)行100除以n(下舍)次循環(huán),這個循環(huán)體執(zhí)行n次普通循環(huán)體的操作
達(dá)夫設(shè)備代碼:(這個8就是我說的n)
var i = items.length % 8; //先循環(huán)余數(shù)次數(shù) while(i){ process(items[i--]); } i = Math.floor(items.length / 8); //再循環(huán)8的整數(shù)倍次數(shù) 循環(huán)體是普通循環(huán)的8倍 可以寫成函數(shù)傳參調(diào)用 while(i){ process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); process(items[i--]); }
最小化屬性查找:
for(var i = 0, len = arr.length; i < len; i++){ ... }
基于函數(shù)的迭代:forEach()
forEach遍歷一個數(shù)組的所有成員,并執(zhí)行一個函數(shù)
arr.forEach(function(value, index, array){ ... })
但是所有情況下?;谘h(huán)的迭代比基于函數(shù)的迭代快8倍,在運行速度要求嚴(yán)格時,基于循環(huán)的迭代優(yōu)先于基于函數(shù)的迭代
條件語句
if-else對比switch:
當(dāng)條件較少時 使用if-else更易讀,而當(dāng)條件較多時if-else性能負(fù)擔(dān)比switch大,易讀性也沒switch好。
優(yōu)化if-else的方法是:盡可能的把可能出現(xiàn)的條件放在首位,比如:
var i = Math.random(1); if(i <= 0.8){ //i小于0.8是幾率最大的,如果i的值滿足i <= 0.8 后面的條件就不會再判斷了 ... }else if(i > 0.8 && i <= 0.9){ ... }else{ ... }
當(dāng)條件很多的時候:(比如10個和10個以上),避免使用條件語句if-else、switch是最佳方式是使用hash表
Memoization
減少工作量就是最好的性能優(yōu)化技術(shù)(你可以理解為,砍需求是為了性能優(yōu)化,這是魯迅說的--魯迅:這句話我還真說過)
Memoization避免重復(fù)工作,緩存前一個計算的結(jié)果為后面的計算所用
比如分別求4、5、6的階乘
求6的階乘的時候,因為我緩存了5的階乘結(jié)果,那么6的階乘就是5的階乘結(jié)果乘以6
function memoizeA(n) { if(!memoizeA.cache){ memoizeA.cache = { "0": 1, "1": 1 } } if(!memoizeA.cache.hasOwnProperty(n)){ memoizeA.cache[n] = n * memoizeA(n-1) } return memoizeA.cache[n] } var a1 = memoizeA(4) console.log(a1) //24 var a2 = memoizeA(5) console.log(a2) //120 var a3 = memoizeA(6) console.log(a3) //720 function memoize(func, cache) { cache = cache || {}; var shell = function (arg) { if(!cache.hasOwnProperty(arg)){ cache[arg] = func(arg); } return cache[arg]; } return shell; } var funCcc = function ccc(n){ if(n == 0){ return 1; }else{ return n*ccc(n-1) } } var a4 = memoize(funCcc,{"0":1,"1":1}); console.log(a4(6)); //720
說明:正則表達(dá)式我不會,這里就不說了
字符串
比較下四中字符串拼接方法的性能:
A:str = str + "a"+"b"
B:str += "a" + "b"
C: arr.join("")
D:str.concat("b","c")
對于A與B比較:B會在內(nèi)存中創(chuàng)建一個臨時字符串,字符串拼接為"ab"后賦給臨時字符串,臨時字符串賦給str;大多數(shù)瀏覽器下A優(yōu)于B,但在IE8及更早的版本中,B優(yōu)于A
關(guān)于join、concat加前兩種拼接的效率:
//+= (function () { var startTime = new Date().getTime(); var str = ""; var addStr = "hello world~, hello xiaojiejie"; for(var i = 0; i < 100000; i++){ str += addStr; } var endTime = new Date().getTime(); console.log("字符串str += a:"); console.log(endTime-startTime); })(); // + (function () { var startTime = new Date().getTime(); var str = ""; var addStr = "hello world~, hello xiaojiejie"; for(var i = 0; i < 100000; i++){ str = str + addStr; } var endTime = new Date().getTime(); console.log("字符串str = str + a:"); console.log(endTime-startTime); })(); //concat (function () { var startTime = new Date().getTime(); var str = ""; var addStr = "hello world~, hello xiaojiejie"; for(var i = 0; i < 100000; i++){ str = str.concat(addStr); } var endTime = new Date().getTime(); console.log("字符串str.concat:"); console.log(endTime-startTime); })(); //join (function () { var startTime = new Date().getTime(); var str = ""; var arr = []; var addStr = "hello world~, hello xiaojiejie"; for(var i = 0; i < 100000; i++){ arr.push(addStr); } str = arr.join(""); var endTime = new Date().getTime(); console.log("字符串join:"); console.log(endTime-startTime); })();
我用這段代碼簡單在chrome65上測試了下,平均下來A>B>C>D,未統(tǒng)計取平均,也沒測試其他瀏覽器
書上說在IE老版本join是比較快的,也是大量字符串拼接的唯一高效方式
詳細(xì)參考 幾種字符串拼接性能
瀏覽器UI線程
用于執(zhí)行JavaScript和更新用戶界面的進(jìn)程被稱為"瀏覽器UI線程",UI線程的工作基于一個隊列系統(tǒng),當(dāng)進(jìn)程空閑時,就會從改隊列提取任務(wù)去執(zhí)行,該任務(wù)可能是JavaScript代碼也可能是UI更新(重繪、重排)。
UI:用戶界面 GUI:圖形用戶界面 這張圖來自 鏈接
瀏覽器限制JavaScript任務(wù)的運行時間,限制兩分鐘,可以防止惡意代碼不斷執(zhí)行來鎖定你的瀏覽器
單個JavaScript操作的花費總時間應(yīng)該小于等于100ms,這就意味著在100ms內(nèi)響應(yīng)用戶的操作,不然就會讓用戶感受到遲鈍感
定時器讓出時間片斷
如果代碼復(fù)雜100ms運營不完,可以使用定時器讓出時間片斷,從而使UI獲得控制權(quán)進(jìn)行更新。
這個例子只是說明JavaScript單線程,定時器可以把任務(wù)放到后面執(zhí)行,方便理解 console.log(111); setTimeout(func(){console.log(222)},0); console.log(333); //111 333 222
JavaScript是單線程,所以定時器可以把JavaScript任務(wù)放到后面,控制權(quán)先交給UI線程
定時器精度有幾毫秒的偏差,,Windows系統(tǒng)中定時器的分辨率為25ms,所以建議延遲最小值設(shè)置為25ms
把一個任務(wù)分解成一系列子任務(wù)
把一個運行時間長的函數(shù)分解為一個個短時間運行的子函數(shù)
使用時間戳計算獲得程序運行時間,以便快速找到運行時間較長的代碼部分進(jìn)行優(yōu)化
重復(fù)的定時器會搶奪UI線程的運行時間,1秒及以上的低頻定時器不會有什么影響,當(dāng)使用高頻100ms-200ms之前的定時器時響應(yīng)會變慢,所以高頻重復(fù)定時器使用要注意
Web Workers (HTML5新特性)
在UI線程外運行,不占用UI線程的時間
來自W3C的worker demo
Web Workers不能修改DOM
運行環(huán)境組成:
一個navigator對象
一個location對象(與window.location相同 屬性-只讀)
一個self對象,指向worker對象
可以引入需要用到的外部文件importScripts()方法
可以使用js對象 Object、Array、Date等
XHR
定時器
close() 立刻停止Worker運行
W3C介紹Web Worker
博文:Web Worker原理和應(yīng)用介紹
實際應(yīng)用場景:處理純數(shù)據(jù)或者與UI線程無關(guān)的長時間運行腳本,個人覺得大量的純計算可以考慮使用
前面說到數(shù)據(jù)存取會影響性能,理所應(yīng)當(dāng)?shù)?,?shù)據(jù)的傳輸同樣影響性能
Ajax通過異步的方式在客戶端和服務(wù)端之間傳輸數(shù)據(jù)。
數(shù)據(jù)傳輸
請求數(shù)據(jù)的五種方式:
A:XMLHTTPRequest(簡稱XHR)
最常用異步異步發(fā)送和接收數(shù)據(jù),包括GET和POST兩種方式
不能跨域
GET--參數(shù)放在url后面,請求得到的數(shù)據(jù)會被緩存,當(dāng)url加參數(shù)超過2048,可以使用POST方式
POST--參數(shù)在頭信息,數(shù)據(jù)不會被緩存
XHR工作原理及優(yōu)缺點參考選我選我
B:動態(tài)腳本注入
其實就是創(chuàng)建一個script元素這個元素的src不受當(dāng)前域限制,但是不能設(shè)置請求頭信息,也就是只能用GET方式
C.Multipart XHR
MXHR荀彧一個HTTP請求就可以傳輸多個數(shù)據(jù)
通過在服務(wù)端講資源打包成一個雙方約定的字符串分割的長字符串發(fā)送到客戶端,然后根據(jù)mime-typed類型和傳入的其他頭信息解析出資源
缺點:資源不能被緩存
D.iframe
E.comet
發(fā)送數(shù)據(jù):XHR、Beacons、
數(shù)據(jù)格式
A.XML
優(yōu)點:通用、格式嚴(yán)格、易于驗證
缺點:冗長、結(jié)構(gòu)復(fù)雜有效數(shù)據(jù)比例低
B.JSON
JSON.parse():JSON-->對象
JSON.stringify():js值-->JSON字符串
文件小、下載快、解析快
C.JSON-P
在客戶端注冊一個callback, 然后把callback的名字傳給服務(wù)器。此時,服務(wù)器先生成 json 數(shù)據(jù)。 然后以 javascript 語法的方式,生成一個function , function 名字就是傳遞上來的參數(shù) jsonp。最后將 json 數(shù)據(jù)直接以入?yún)⒌姆绞?,放置?function 中,這樣就生成了一段 js 語法的文檔,返回給客戶端。
D.HTML
E.自定義數(shù)據(jù)格式
Ajax性能
最快的Ajax請求就是沒有請求(貧一句:最快的寫程序方式就是天天跟產(chǎn)品拌嘴,砍需求,那啥,我先跑了,產(chǎn)品拿著刀追來了)
避免不必要的請求:
服務(wù)端設(shè)置HTTP頭信息確保響應(yīng)會被瀏覽器緩存
客戶端講獲取的信息存到本地避免再次請求(localstorage sessionstorage cookice)
設(shè)置HTTP頭信息,expiresgaosu告訴瀏覽器緩存多久
減少HTTP請求,合并css、js、圖片資源文件等或使用MXHR
通過次要文件用Ajax獲取可縮短頁面加載時間
避免雙重求值
eval()、Function慎用,定時器第一個參數(shù)建議函數(shù)而不是字符串都能避免字符串雙重求值
使用對象或者數(shù)組直接量
直接量:
var obj = { name:... age:... }
非直接量:
var obj = new Object() obj.name = ... ...
運行時直接量比非直接量快
避免重復(fù)工作
A:延遲加載(懶加載)
進(jìn)入函數(shù)-->判斷條件-->重寫函數(shù)
B:條件預(yù)加載
函數(shù)調(diào)用前提前進(jìn)行條件檢測
var addEvent = doc.addEventListener ? funcA : funcB
使用JavaScript速度快的部分
A.位操作
B.原生方法,首先原生方法是最快的,而且瀏覽器會緩存部分原生方法
C.復(fù)雜計算時多使用Math對象
D.querySelector和querySelectorAll是查詢最快的
當(dāng)用Document類型調(diào)用querySelector()方法時,會在文檔元素范圍內(nèi)查找匹配的元素;而當(dāng)用Element類型調(diào)用querySelector()方法時,只會在這個元素的后代元素中去查找匹配的元素。若不存在匹配的元素,則這兩種類型調(diào)用該方法時,均返回null。
這一章講的都是其他章節(jié)的優(yōu)化原理的實踐,主要有:
1.合并多個js文件
2.預(yù)處理js文件
3.js壓縮
4.js的HTTP壓縮
5.緩存js文件
6.處理緩存問題
7.使用內(nèi)容分發(fā)網(wǎng)絡(luò)(CDN)這個有點效果顯著的感覺,前年第一次用的時候感覺快了很多,打個比方就是:
京東網(wǎng)上水果蔬菜超市,假設(shè)你在上海買了一個榴蓮,京東可以在上海的倉庫給你發(fā)貨,如果上海沒有他們的倉庫,就在離你最近的一個倉庫發(fā)貨,以保證最快速度送到你手上(吃什么不好,吃榴蓮,別人會說食屎拉你)。這個倉庫放的就是靜態(tài)資源文件,根據(jù)請求發(fā)出的位置找到最近的CDN節(jié)點把資源返回給請求端,大概是這個意思,具體原理參考CDN原理
現(xiàn)在很多方式都在gulp、webpack工具里進(jìn)行了,方便省事
JavaScript性能分析
使用Date對象實例減去另一個實例獲得任務(wù)運行時間毫秒數(shù)
匿名函數(shù)
測量分析匿名函數(shù)的方法就是給匿名函數(shù)加上名字
調(diào)試工具
個人比較喜歡chrome調(diào)試工具
貢獻(xiàn)幾個比較全的教程
基礎(chǔ)篇
優(yōu)化篇
實戰(zhàn)1
實戰(zhàn)2
英文使用介紹
腳本阻塞
Safari4、IE8、Firefox3.5、chrome及以上允許腳本并行下載,但阻塞運行,雖然文件下載快了,但是頁面渲染任會阻塞直到腳本運行完
對運行慢的腳本進(jìn)行優(yōu)化或重構(gòu),不必要的腳本等到等到頁面渲染完成再加載
Page Speed
顯示解析和運行JavaScript消耗的時間,指明可以延長加載的腳本,并報告沒被使用的函數(shù)
Fiddler
Fiddler是一個HTTP調(diào)試代理工具,能檢測到網(wǎng)絡(luò)中所有資源,以定位加載瓶頸
YSlow
YSlow工具可以深入觀察頁面初始加載和運行過程的整體性能
WebPagetest
WebPagetest:根據(jù)用戶瀏覽器真實的連接速度,在全球范圍內(nèi)進(jìn)行網(wǎng)頁速度測試,并提供詳細(xì)的優(yōu)化建議。
WebPagetest
Google PageSpeed
PageSpeed 根據(jù)網(wǎng)頁最佳實踐分析和優(yōu)化測試的網(wǎng)頁。
Pingdom 網(wǎng)站速度測試
輸入 URL 地址,即可測試頁面加載速度,分析并找出性能瓶頸。
Pingdom 網(wǎng)站速度測試
還有很多類似工具:參考前端性能優(yōu)化和測試工具總結(jié)
本文檔主干內(nèi)容來自于《高性能JavaScript》及其他其他博客并注明出處,如有侵權(quán)請聯(lián)系作者刪除~
后續(xù)會通過舉證說明更多方案的效果,不斷完善此文檔
注:內(nèi)容有不當(dāng)或者錯誤處請指正~轉(zhuǎn)載請注明出處~謝謝合作!
文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/54525.html
摘要:然后執(zhí)行環(huán)境會創(chuàng)建一個活動對象,活動對象作為函數(shù)運行的變量對象,包含所有局部變量命名參數(shù)參數(shù)集合和,當(dāng)執(zhí)行環(huán)境銷毀,活動對象也被銷毀。 高性能JavaScript整理總結(jié) 關(guān)于前端性能優(yōu)化:首先想到的是雅虎軍規(guī)34條然后最近看了《高性能JavaScript》大概的把書中提到大部分知識梳理了下并加上部分個人理解這本書有參考雅虎特別性能小組的研究成果,所以跟34 軍規(guī)有很多相似之處有不當(dāng)之...
摘要:前端每周清單年度總結(jié)與盤點在過去的八個月中,我?guī)缀踔蛔隽藘杉?,工作與整理前端每周清單。本文末尾我會附上清單線索來源與目前共期清單的地址,感謝每一位閱讀鼓勵過的朋友,希望你們能夠繼續(xù)支持未來的每周清單。 showImg(https://segmentfault.com/img/remote/1460000010890043); 前端每周清單年度總結(jié)與盤點 在過去的八個月中,我?guī)缀踔蛔隽?..
閱讀 1904·2021-11-22 09:34
閱讀 3040·2021-09-28 09:35
閱讀 13499·2021-09-09 11:34
閱讀 3608·2019-08-29 16:25
閱讀 2840·2019-08-29 15:23
閱讀 2051·2019-08-28 17:55
閱讀 2439·2019-08-26 17:04
閱讀 3056·2019-08-26 12:21