高性能JS筆記

第九章 構(gòu)建并部署高性能JavaScript應(yīng)用

1 合并多個(gè)JS文件示绊,減少HTTP請(qǐng)求數(shù)

2 預(yù)處理JS文件斤儿,雖不會(huì)提高性能,但允許你做其他事情贷岸,如有條件的插入測(cè)試代碼來(lái)衡 量應(yīng)用程序的性能

3 壓縮JS和CSS

4 只要是能在構(gòu)建時(shí)完成的工作就不要留到運(yùn)行時(shí)去做跃闹,如合并嵌削、壓縮、預(yù)處理等

5 JS的壓縮有很多工具望艺,如gzip (適合純文本苛秕,有圖片不行)、YUI Compressor和Packer找默,最佳實(shí)踐是使用YUI Compressor合并再使用gzip壓縮艇劫,Packer可用于網(wǎng)速較慢或不支持Gzip的情況

6 緩存JS文件。服務(wù)器可通過(guò)“Expire HTTP響應(yīng)頭”來(lái)告訴客戶(hù)端一個(gè)資源應(yīng)當(dāng)緩存多長(zhǎng)時(shí)間惩激,可通過(guò)設(shè)置緩存時(shí)間為一年將緩存時(shí)間設(shè)為永不過(guò)期店煞,然而有的瀏覽器可能會(huì)有緩存限制,此時(shí)可考慮采用客戶(hù)端存儲(chǔ)機(jī)制风钻,如cookies顷蟀,localstorage及sessionstorage,不過(guò)此時(shí)JS代碼必須自行控制到期時(shí)間骡技,另外還可以使用HTML5離線(xiàn)應(yīng)用緩存技術(shù)鸣个,缺點(diǎn)是要確保用戶(hù)下載的都是最新的內(nèi)容

7 使用內(nèi)容分發(fā)網(wǎng)絡(luò)CDN,可增強(qiáng)WEB應(yīng)用的可靠性布朦,可擴(kuò)展性還能提高性能囤萤。通過(guò)向地理位置最近的用戶(hù)傳輸內(nèi)容,CDN能極大減少網(wǎng)絡(luò)延時(shí)

第八章 編程實(shí)踐

1 避免雙重求值是趴。JS允許你在程序中提取一個(gè)包含代碼的字符串涛舍,然后動(dòng)態(tài)執(zhí)行它。有四種標(biāo)準(zhǔn)方法可以實(shí)現(xiàn):eval右遭,Function()構(gòu)造函數(shù)做盅,setTimeout()和setInterval()缤削,每個(gè)方法都允許你傳入一個(gè)JS代碼字符串并執(zhí)行它窘哈,代碼字符串指?jìng)魅氲氖亲址珗?zhí)行時(shí)用的是該字符串所對(duì)應(yīng)的值亭敢。這些方法都會(huì)導(dǎo)致雙重求值滚婉,因?yàn)槊看握{(diào)用這些函數(shù)時(shí)都要?jiǎng)?chuàng)建一個(gè)新的解釋器/編譯器實(shí)例,從而導(dǎo)致代碼執(zhí)行速度變慢帅刀。故沒(méi)必要使用eval()和Function時(shí)就避免使用他們让腹。至于setTimeout()和setInterval()远剩,建議傳入函數(shù)而不是字符串來(lái)作為第一個(gè)參數(shù)

2 使用Object/Array直接量

Var Myobject=new『稀Object()瓜晤;

Myobject.name="nick";

Var「鼓伞Myobject={

name:"nick"

推薦使用第二種方式:1 速度快 ×÷印2 省空間

3 不做重復(fù)工作

1 延遲加載(在每個(gè)分支語(yǔ)句里覆蓋函數(shù)即可實(shí)現(xiàn))

2 條件預(yù)加載(在腳本加載時(shí)就檢測(cè),而不是加載后)

4 使用速度快的部分

1 進(jìn)行數(shù)學(xué)運(yùn)算時(shí)使用位運(yùn)算或使用Math對(duì)象的API

2 盡量使用原生JS方法嘲恍,如DOM操作查找節(jié)點(diǎn)時(shí)可用querySelecto r()方法

第七章 AJAX

1 數(shù)據(jù)傳輸--請(qǐng)求數(shù)據(jù)技術(shù)

A .XHR

當(dāng)使用get方式時(shí)足画,請(qǐng)求的資源會(huì)被緩存,只有當(dāng)url加上參數(shù)的長(zhǎng)度接近或超過(guò)2048個(gè)字符時(shí)才應(yīng)該用post佃牛。不能跨域請(qǐng)求數(shù)據(jù)

B. 動(dòng)態(tài)腳本注入

可跨域請(qǐng)求數(shù)據(jù)淹辞,只需用JS動(dòng)態(tài)創(chuàng)建一個(gè)腳本標(biāo)簽,然后設(shè)置他的src屬性為不同域的URL即可俘侠,不能設(shè)置請(qǐng)求的頭信息象缀,只能使用get方式,也不能訪問(wèn)請(qǐng)求的頭信息爷速,不能把響應(yīng)消息作為字符串處理攻冷。響應(yīng)消息是作為腳本標(biāo)簽的源碼,故必須是可執(zhí)行的JS代碼遍希,不能使用純XML等曼,純Json或其他任何格式的數(shù)據(jù),無(wú)論哪種格式凿蒜,都必須封裝在一個(gè)回調(diào)函數(shù)中禁谦。

C .MXHR

該技術(shù)允許客戶(hù)端只用一個(gè)HTTP請(qǐng)求就可以從服務(wù)器想客戶(hù)端傳送多個(gè)資源。他通過(guò)在服務(wù)器端將資源打包成一個(gè)雙方約定的字符串分割的長(zhǎng)字符串并發(fā)送到客戶(hù)端废封,然后用JS代碼處理這個(gè)長(zhǎng)字符串州泊,并根據(jù)mime-type類(lèi)型和傳入的其他頭信息解析出每個(gè)資源。該技術(shù)最大的缺點(diǎn)是不能緩存數(shù)據(jù)

2 數(shù)據(jù)傳輸--發(fā)送數(shù)據(jù)技術(shù)

A .XHR

B. Beacons(圖片信標(biāo))

類(lèi)似于動(dòng)態(tài)腳本注入漂洋,使用JS創(chuàng)建一個(gè)新的Image對(duì)象遥皂,并把src屬性設(shè)置為服務(wù)器上腳本的URL,注意沒(méi)有創(chuàng)建img元素或把他插入DOM刽漂,服務(wù)器端無(wú)需向客戶(hù)端返回回饋信息演训,這是給服務(wù)器回傳信息的最有效的方式。缺點(diǎn):不能使用post贝咙,接收到的響應(yīng)類(lèi)型是有限的样悟。適用于只關(guān)心發(fā)送數(shù)據(jù)到服務(wù)器,不關(guān)心返回?cái)?shù)據(jù)

3 數(shù)據(jù)格式

A XML

Xpath

B JSON

XHR+JSON,JSON數(shù)據(jù)被當(dāng)成字符串返回窟她,然后使用eval()轉(zhuǎn)換為原生對(duì)象

動(dòng)態(tài)腳本注入+JSON-P陈症,JSON數(shù)據(jù)被當(dāng)成JS文件并作為原生代碼執(zhí)行

C HTML

D 自定義格式

速度最快的是使用數(shù)組形式的JSON-P

4 AJAX性能指南之緩存數(shù)據(jù)

1 設(shè)置HTTP頭信息

若希望AJAX響應(yīng)被瀏覽器緩存,那么必須使用get方式發(fā)出請(qǐng)求震糖,并在服務(wù)器端設(shè)置HTTP頭信息中的expire時(shí)間

2 本地?cái)?shù)據(jù)存儲(chǔ)

除了依賴(lài)瀏覽器處理緩存外录肯,還可以使用手工方式實(shí)現(xiàn),即直接把服務(wù)器接收到的數(shù)據(jù)儲(chǔ)存起來(lái)吊说,把響應(yīng)文本保存到一個(gè)對(duì)象中嘁信,以URL為鍵值作為索引

var localCathe={};

function xhrRequest(url,callback){

//檢查此URL的本地緩存

if(localCathe[url]){

callback.success(localCathe[url]);

return;

}

//此URL緩存不存在

var req=creatXhrObject();

req.onerror=function(){

callback.error();

};

req.onreadystatechange=function(){

if(req.readyState==4){

if(req.responseText===''||req.status=='404'){

callback.error();

return;

}

//存儲(chǔ)相應(yīng)文本到本地緩存

localCathe[url]=req.responseText;

callback.success(req.responseText);

}

};

req.open("GET",url,true);

req.send(null);

}

第五章 字符串與正則表達(dá)式

1 字符串連接

str+=s1+s2與str=str+s1+s2的區(qū)別:

前者經(jīng)歷四個(gè)步驟:1 在內(nèi)存中創(chuàng)建一個(gè)臨時(shí)字符串2連接s1和s2后賦給該變量3臨時(shí)字 符串與str連接4 結(jié)果賦給str

后者經(jīng)歷兩個(gè)步驟:1將s1拷貝到str末尾 2將s2拷貝到str+s1的末尾

后者避免了使用臨時(shí)變量,性能會(huì)有提升

2 數(shù)組項(xiàng)連接

Array.prototype.join方法將數(shù)組的所有元素合并成一個(gè)字符串

String.prototype.concat方法通常比+疏叨,+=操作符慢

第四章 算法與流程控制

1 JS中共有四種循環(huán)潘靖,for while do-while for-in,其中for-in用于遍歷對(duì)象中的屬性,

2 改善循環(huán)性能的最佳方式是減少每次迭代的運(yùn)算量(最小化屬性查找和倒敘循環(huán)法)和減 少循環(huán)迭代次數(shù)(達(dá)夫設(shè)備法)

3 通常蚤蔓,switch總是比if-else快卦溢,但并不總是最佳解決方案

4 判斷條件較多時(shí),使用查找表比if-else和switch更快

5 瀏覽器調(diào)用棧大小限制了遞歸算法在JS中的應(yīng)用秀又,棧溢出錯(cuò)誤會(huì)導(dǎo)致其他代碼中斷執(zhí)行单寂, 若遇到這種情況,可將方法改為迭代算法或使用Memoization(使用緩存技術(shù))來(lái)避免重 復(fù)計(jì)算

第三章 DOM編程

1 減少訪問(wèn)DOM的次數(shù)吐辙,把運(yùn)算盡量留在ECMAScript這邊

2 關(guān)于修改頁(yè)面區(qū)域的最佳方案:對(duì)于舊版本的瀏覽器宣决,建議使用innerHTML;對(duì)于新版本的瀏覽器昏苏,建議使用DOM方法(creatElement等方法)

3 使用DOM方法更新頁(yè)面內(nèi)容的另一個(gè)途徑是克隆已有元素尊沸,而不是創(chuàng)建新元素,即使用cloneNode方法代替creatElement方法贤惯,在大多數(shù)瀏覽器中洼专,克隆更有效率

4 HTML集合是包含了DOM節(jié)點(diǎn)引用的類(lèi)數(shù)組對(duì)象,返回該集合的方法有:getElementsByName() getElementsByClassName() getElementsByTagName() 返回該集合的屬性有:document.images document.links document.forms document.forms[0].elements

類(lèi)數(shù)組對(duì)象沒(méi)有push和slice等數(shù)組方法孵构,但可以通過(guò)下標(biāo)訪問(wèn)列表中的元素屁商,也提供了length屬性,但HTML集合處于一種實(shí)時(shí)狀態(tài)颈墅,即當(dāng)?shù)讓游臋n對(duì)象更新時(shí)他也會(huì)自動(dòng)更新蜡镶。

Array.prototype.slice.call(HTML集合)可將集合轉(zhuǎn)化為JS數(shù)組

5 DOM遍歷 1 當(dāng)你需要從某一個(gè)DOM元素開(kāi)始操作周?chē)脑鼗蜻f歸查找所有子節(jié)點(diǎn),你可以使用childNodes或nextSibling,在IE中nextSilbing比childNodes快恤筛,其他瀏覽器中差不多 2 使用children代替childNodes 3 使用querySelector和querySelectorAll代替getElementById等方法官还,用之前要檢查瀏覽器是否支持這兩個(gè)函數(shù)

6 重繪與重排

瀏覽器下載完頁(yè)面中的所有組件---HTML標(biāo)記、JS叹俏、CSS妻枕、圖片之后會(huì)解析并生成兩個(gè)內(nèi)部數(shù)據(jù)結(jié)構(gòu):DOM樹(shù)和渲染樹(shù)僻族。當(dāng)DOM的變化影響了元素的集合屬性(寬和高)粘驰,會(huì)引發(fā)重排操作屡谐,完成重排后再進(jìn)行重繪操作。重排和重繪都是代價(jià)昂貴的操作蝌数,應(yīng)當(dāng)避免愕掏。下列情況會(huì)導(dǎo)致重排:(當(dāng)滾動(dòng)條出現(xiàn)時(shí)會(huì)導(dǎo)致整個(gè)頁(yè)面的重排)

1 添加或者刪除可見(jiàn)的DOM元素

2 元素位置改變

3 元素尺寸改變

4 元素內(nèi)容改變(例如:一個(gè)文本被另一個(gè)不同尺寸的圖片替代)

5 頁(yè)面渲染初始化(這個(gè)無(wú)法避免)

6 瀏覽器窗口尺寸改變

注意:1 盡量不要在布局信息改變時(shí)做查詢(xún),這會(huì)導(dǎo)致強(qiáng)制刷新隊(duì)列并要求計(jì)劃任務(wù)立刻執(zhí) 行(多數(shù)瀏覽器通過(guò)隊(duì)列化修改并批量執(zhí)行來(lái)優(yōu)化重排過(guò)程)

1 offsetTop, offsetLeft, offsetWidth, offsetHeight

2 scrollTop, scrollLeft, scrollWidth, scrollHeight

3 clientTop, clientLeft, clientWidth, clientHeight

4 getComputedStyle() (currentStyle in IE)

[圖片上傳失敗...(image-e70534-1519915919725)]

2 最小化重排和重繪(將多個(gè)操作合并為一個(gè)顶伞,從而只會(huì)修改DOM一次饵撑,如cssText 屬性)

3 批量修改DOM:1 是元素脫離文檔流2對(duì)其應(yīng)用多重改變3把元素帶回文檔中

讓元素脫離文檔流的方法:1隱藏元素2使用文檔片段(在當(dāng)前DOM之外構(gòu)建一 個(gè)子樹(shù),在拷貝回文檔)3 將原始元素拷貝到一個(gè)脫離文檔的節(jié)點(diǎn)中唆貌,修改副本再 替換

4 動(dòng)畫(huà)中使用絕對(duì)定位滑潘,使用拖放代理,使用事件委托減少事件處理器的數(shù)量

第二章 數(shù)據(jù)訪問(wèn)

1 JS中有四種基本的數(shù)據(jù)存取位置:直接量(如字符串锨咙,數(shù)字语卤,布爾,對(duì)象等)酪刀,變量(用var定義)粹舵,數(shù)組元素,對(duì)象成員骂倘,一般前兩者速度快于后兩者

2 通常來(lái)說(shuō)眼滤,可以通過(guò)把常用的對(duì)象成員、數(shù)組元素历涝、跨域變量保存在局部變量中來(lái)改善JS性能诅需,因?yàn)榫植孔兞吭L問(wèn)速度最快(緩存全局變量)

3 對(duì)象的方法不要賦值給局部變量,把一個(gè)方法保存在局部變量會(huì)導(dǎo)致this綁定到window

第一章 加載與執(zhí)行

1 JS代碼應(yīng)該放在</body>標(biāo)簽之前

2 減少<script>標(biāo)簽(每下載一個(gè)js文件都會(huì)執(zhí)行荧库,從而導(dǎo)致延時(shí)诱担。可通過(guò)合并JS文件達(dá)到)

3 不要把內(nèi)嵌腳本緊跟在<link>標(biāo)簽之后(會(huì)導(dǎo)致頁(yè)面阻塞去等待樣式表下載)

4 無(wú)阻塞腳本技術(shù):1 使用defer屬性电爹,只有IE4+和Firefox3.5+支持蔫仙。帶有defer屬性的script 元素在DOM加載之前不會(huì)執(zhí)行,而是在onload事件處理器執(zhí)行之前被調(diào)用

2 動(dòng)態(tài)腳本元素

function loadScript (url,callback) {

var script=document.createElement("script");

script.type="text/javascript";

if (script.readyState) {//針對(duì)IE

script.onreadystatechange=function () {

if (script.readyState=="loaded"||script.readyState=="complete") {

script.onreadystatechange=null;

callback();

}

};

}else{//針對(duì)其他瀏覽器

script.onload=function(){

callback();

};

}

script.src=url;

document.getElementsByTagName("head")[0].appendChild(script);

}

3 XMLHttpRequest腳本注入

var xhr=new XMLHttpRequest();

xhr.open("get",file1.js,true);

xhr.onreadystatechange=function(){

if(xhr.readyState==4){

if(xhr.status>=200&&xhr.status<300||xhr.status==304){

var script=document.creatElement("script");

script.type="text/javascript";

script.text=xhr.responseText;

document.body.appendChild(script);

}

}

};

xhr.send(null);

優(yōu)點(diǎn):下載后不會(huì)自動(dòng)執(zhí)行丐箩;適用于所有主流瀏覽器

缺點(diǎn):請(qǐng)求的JS文件必須與所請(qǐng)求的頁(yè)面同域摇邦,即不能從CDN下載

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市屎勘,隨后出現(xiàn)的幾起案子施籍,更是在濱河造成了極大的恐慌,老刑警劉巖概漱,帶你破解...
    沈念sama閱讀 217,277評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件丑慎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)竿裂,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,689評(píng)論 3 393
  • 文/潘曉璐 我一進(jìn)店門(mén)玉吁,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人腻异,你說(shuō)我怎么就攤上這事进副。” “怎么了悔常?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,624評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵影斑,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我机打,道長(zhǎng)矫户,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,356評(píng)論 1 293
  • 正文 為了忘掉前任残邀,我火速辦了婚禮吏垮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘罐旗。我一直安慰自己膳汪,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,402評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布九秀。 她就那樣靜靜地躺著遗嗽,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鼓蜒。 梳的紋絲不亂的頭發(fā)上痹换,一...
    開(kāi)封第一講書(shū)人閱讀 51,292評(píng)論 1 301
  • 那天,我揣著相機(jī)與錄音都弹,去河邊找鬼娇豫。 笑死,一個(gè)胖子當(dāng)著我的面吹牛畅厢,可吹牛的內(nèi)容都是我干的冯痢。 我是一名探鬼主播,決...
    沈念sama閱讀 40,135評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼框杜,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼浦楣!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起咪辱,我...
    開(kāi)封第一講書(shū)人閱讀 38,992評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤振劳,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后油狂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體历恐,經(jīng)...
    沈念sama閱讀 45,429評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡寸癌,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,636評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了弱贼。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片蒸苇。...
    茶點(diǎn)故事閱讀 39,785評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖哮洽,靈堂內(nèi)的尸體忽然破棺而出填渠,到底是詐尸還是另有隱情弦聂,我是刑警寧澤鸟辅,帶...
    沈念sama閱讀 35,492評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站莺葫,受9級(jí)特大地震影響匪凉,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜捺檬,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,092評(píng)論 3 328
  • 文/蒙蒙 一再层、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧堡纬,春花似錦聂受、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,723評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至炮叶,卻和暖如春碗旅,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背镜悉。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,858評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工祟辟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人侣肄。 一個(gè)月前我還...
    沈念sama閱讀 47,891評(píng)論 2 370
  • 正文 我出身青樓旧困,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親稼锅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子叮喳,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,713評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容