比較下四中字符串拼接方法的性能:
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ì)參考 幾種字符串拼接性能
用于執(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ù)定時器使用要注意。
在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ù)的五種方式:
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、
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請求就是沒有請求(貧一句:最快的寫程序方式就是天天跟產(chǎn)品拌嘴,砍需求,那啥,我先跑了,產(chǎn)品拿著刀追來了)
避免不必要的請求:
服務(wù)端設(shè)置HTTP頭信息確保響應(yīng)會被瀏覽器緩存
客戶端講獲取的信息存到本地避免再次請求(localstorage sessionstorage cookice)
設(shè)置HTTP頭信息,expiresgaosu告訴瀏覽器緩存多久
減少HTTP請求,合并css、js、圖片資源文件等或使用MXHR
通過次要文件用Ajax獲取可縮短頁面加載時間。
eval()、Function慎用,定時器第一個參數(shù)建議函數(shù)而不是字符串都能避免字符串雙重求值
直接量:
var obj = {
name:...
age:...
}
非直接量:
var obj = new Object()
obj.name = ...
...
運行時直接量比非直接量快
A:延遲加載(懶加載)
進(jìn)入函數(shù)-->判斷條件-->重寫函數(shù)
B:條件預(yù)加載
函數(shù)調(diào)用前提前進(jìn)行條件檢測
var addEvent = doc.addEventListener ? funcA : funcB
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)行了,方便省事。
使用Date對象實例減去另一個實例獲得任務(wù)運行時間毫秒數(shù)。
測量分析匿名函數(shù)的方法就是給匿名函數(shù)加上名字。
個人比較喜歡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),不必要的腳本等到等到頁面渲染完成再加載。
顯示解析和運行JavaScript消耗的時間,指明可以延長加載的腳本,并報告沒被使用的函數(shù)。
Fiddler是一個HTTP調(diào)試代理工具,能檢測到網(wǎng)絡(luò)中所有資源,以定位加載瓶頸。
YSlow工具可以深入觀察頁面初始加載和運行過程的整體性能。
WebPagetest:根據(jù)用戶瀏覽器真實的連接速度,在全球范圍內(nèi)進(jìn)行網(wǎng)頁速度測試,并提供詳細(xì)的優(yōu)化建議。
WebPagetest
PageSpeed 根據(jù)網(wǎng)頁最佳實踐分析和優(yōu)化測試的網(wǎng)頁。
輸入 URL 地址,即可測試頁面加載速度,分析并找出性能瓶頸。
Pingdom 網(wǎng)站速度測試