JavaScript提高網(wǎng)站性能優(yōu)化的建議(二)
來源:易賢網(wǎng) 閱讀:667 次 日期:2016-07-29 14:19:00
溫馨提示:易賢網(wǎng)小編為您整理了“JavaScript提高網(wǎng)站性能優(yōu)化的建議(二)”,方便廣大網(wǎng)友查閱!

這篇文章主要介紹了JavaScript提高網(wǎng)站性能優(yōu)化的建議(二)的相關(guān)資料,需要的朋友可以參考下

在javascript關(guān)于提高網(wǎng)站性能的幾點(diǎn)建議(一)中,從HTTP請(qǐng)求到頁(yè)面渲染幾個(gè)方面對(duì)提高網(wǎng)站性能提出了幾點(diǎn)建議,本文是學(xué)習(xí)Steve Sounders的另外一本書《高性能網(wǎng)站建設(shè)進(jìn)階指南》之后,從JavaScript性能的角度進(jìn)行總結(jié)概括,諸君共勉。

JavaScript性能是實(shí)現(xiàn)高性能Web應(yīng)用程序的關(guān)鍵

——Steve Sounders

1 利用js作用域鏈

作用域鏈(scope chain)

當(dāng)執(zhí)行一段JavaScript代碼(全局代碼或函數(shù))時(shí),JavaScript引擎會(huì)創(chuàng)建為其創(chuàng)建一個(gè)作用域又稱為執(zhí)行上下文(Execution Context),在頁(yè)面加載后會(huì)首先創(chuàng)建一個(gè)全局的作用域,然后每執(zhí)行一個(gè)函數(shù),會(huì)建立一個(gè)對(duì)應(yīng)的作用域,從而形成了一條作用域鏈。每個(gè)作用域都有一條對(duì)應(yīng)的作用域鏈,鏈頭是全局作用域,鏈尾是當(dāng)前函數(shù)作用域。

作用域鏈的作用是用于解析標(biāo)識(shí)符,當(dāng)函數(shù)被創(chuàng)建時(shí)(不是執(zhí)行),會(huì)將this、arguments、命名參數(shù)和該函數(shù)中的所有局部變量添加到該當(dāng)前作用域中,當(dāng)JavaScript需要查找變量X的時(shí)候(這個(gè)過程稱為變量解析),它首先會(huì)從作用域鏈中的鏈尾也就是當(dāng)前作用域進(jìn)行查找是否有X屬性,如果沒有找到就順著作用域鏈繼續(xù)查找,直到查找到鏈頭,也就是全局作用域鏈,仍未找到該變量的話,就認(rèn)為這段代碼的作用域鏈上不存在x變量,并拋出一個(gè)引用錯(cuò)誤(ReferenceError)的異常。

管理好作用域鏈的深度,是一種只要少量工作就能提高性能的簡(jiǎn)易方法,我們應(yīng)避免因無意中增長(zhǎng)了作用域鏈而導(dǎo)致執(zhí)行速度變得緩慢。

使用局部變量(盡量縮短作用域鏈)

如果理解了作用域鏈的概念,那么我們應(yīng)該清楚JavaScript引擎對(duì)變量的解析時(shí)間跟作用域鏈的深度有關(guān),顯而易見,局部變量由于處于鏈尾,存取速度是最快的,因此,一個(gè)好的經(jīng)驗(yàn)是:任何非局部變量使用超過一次時(shí),請(qǐng)使用局部變量將其存儲(chǔ)下來,例如:

function changeDiv(){

document.getELementById('myDiv').className = 'changed';

document.getELementById('myDiv').style.height = 150;

}

這里myDiv這個(gè)dom元素被引用了兩次,為了更快的引用,我們應(yīng)該用一個(gè)局部變量將其存儲(chǔ)下來,這樣做的好處不僅縮短了作用域鏈,而且避免了DOM元素的重復(fù)查詢:

function changeDiv(){

var myDivStyle = document.getElementById('myDiv').style;

myDiv.className = 300;

myDiv.style.height = 150;

}

避免使用with(不要增長(zhǎng)作用域鏈)

一般在代碼執(zhí)行過程中,函數(shù)的作用域鏈?zhǔn)枪潭ǖ?,然而with可以臨時(shí)增長(zhǎng)函數(shù)的作用域鏈。with用于將對(duì)象屬性作為局部變量來顯示,使其便于訪問,例如:

var user = {

name:'vicfeel',

age:'23'

};

function showUser(){

var local = 0;

with(user){

console.log("姓名" + name);

console.log("年齡" + age);

console.log(local);

}

}

showUser();

這個(gè)例子中,通過with在showUser作用域鏈的鏈尾中又增加了一個(gè)臨時(shí)作用域,該作用域存儲(chǔ)著user對(duì)象的所有屬性,也就是增長(zhǎng)了with這段代碼的作用域鏈,在這段代碼中,局部變量像local從鏈尾的第一個(gè)對(duì)象變成了第二個(gè),自然減慢了標(biāo)識(shí)符的存取。直到with語(yǔ)句結(jié)束,作用域鏈恢復(fù)增長(zhǎng)。正因?yàn)閣ith的這個(gè)缺陷,我們應(yīng)盡量避免使用with關(guān)鍵字。

2 更合理的流控制

JavaScript與其它編程語(yǔ)言一樣,擁有一些流控制語(yǔ)句(循環(huán)、條件等),在每個(gè)環(huán)節(jié)上使用恰當(dāng)?shù)恼Z(yǔ)句能極大的提高腳本的運(yùn)行速度。

快速條件判斷

提到條件判斷,首先要避免的一種使用方式:

if(value == 0){

return result0;

}

else if(value == 1){

return result1;

}

else if(value == 2){

return result2;

}

else if(value == 3){

return result3;

}

else if(value == 4){

return result4;

}

else if(value == 5){

return result5;

}

else if(value == 6){

return result6;

}

else{

return result7;

}

這種使用if進(jìn)行條件判斷的方式存在的主要問題是層次太深,當(dāng)我要value = 7時(shí),消耗時(shí)間要比value = 0長(zhǎng)很多,大大損耗了性能,同時(shí)可讀性很差。

一種更好的方式,利用switch進(jìn)行判斷。

swithc(value){

case 0:

return result0;

case 1:

return result1;

case 2:

return result2;

case 3:

return result3;

case 4:

return result4;

case 5:

return result5;

case 6:

return result6;

default:

return result7;

}

這樣不僅提高了可讀性,查詢時(shí)間也要比if更快。但是如果只有一兩個(gè)條件時(shí),if是比switch更快的

在JavaScript中,條件查詢還有另外一種方式,之前的例子是根據(jù)值返回不同的值,剛好可以利用數(shù)組實(shí)現(xiàn)hash表的映射查詢。

//定義數(shù)組

var results = [result0,result1,result2,result3,result4,result5,result6,result7];

//查詢結(jié)果

return results[value];

這種數(shù)組的方式,在查詢范圍很大時(shí)才更加有效,因?yàn)樗槐貦z測(cè)上下邊界,只需要填入索引值就可以查詢了。它的局限性在于條件對(duì)應(yīng)的是單一值,而不是一系列操作。因此要綜合實(shí)際情況,選擇合適的條件判斷方式,發(fā)揮性能最大化。

快速循環(huán)

JavaScript中存在4種循環(huán)方式for循環(huán)、do-while循環(huán)、while循環(huán)和for-in循環(huán)。下面是一個(gè)很常用的循環(huán)使用方式:

var values = [1,2,3,4,5];

for(var i = 0;i < values.length;i++){

process(values[i]);

}

我們可以看到,這段代碼最明顯可以優(yōu)化的地方在于values.length,每次循環(huán)i都要和values的長(zhǎng)度進(jìn)行比較,而查詢屬性要比局部變量更耗時(shí),如果循環(huán)次數(shù)越大,這種耗時(shí)就越明顯,因此可以這樣優(yōu)化:

var values = [1,2,3,4,5];

var length = values.length;//局部變量存儲(chǔ)數(shù)組長(zhǎng)度

for(var i = 0;i < length;i++){

process(values[i]);

}

這段代碼還可以繼續(xù)優(yōu)化,將循環(huán)變量遞減到0,而不是遞加到總長(zhǎng)度。

var values = [1,2,3,4,5];

var length = values.length;

for(var i = length;i--;){ //遞減到0

process(values[i]);

}

這里將循環(huán)結(jié)束改造為與0比較,所以每個(gè)循環(huán)的速度更快了,根據(jù)循環(huán)的復(fù)雜度不同,這種簡(jiǎn)單改變可以比原來節(jié)約大概50%的時(shí)間。

更多信息請(qǐng)查看網(wǎng)絡(luò)編程
易賢網(wǎng)手機(jī)網(wǎng)站地址:JavaScript提高網(wǎng)站性能優(yōu)化的建議(二)
由于各方面情況的不斷調(diào)整與變化,易賢網(wǎng)提供的所有考試信息和咨詢回復(fù)僅供參考,敬請(qǐng)考生以權(quán)威部門公布的正式信息和咨詢?yōu)闇?zhǔn)!
關(guān)于我們 | 聯(lián)系我們 | 人才招聘 | 網(wǎng)站聲明 | 網(wǎng)站幫助 | 非正式的簡(jiǎn)要咨詢 | 簡(jiǎn)要咨詢須知 | 加入群交流 | 手機(jī)站點(diǎn) | 投訴建議
工業(yè)和信息化部備案號(hào):滇ICP備2023014141號(hào)-1 云南省教育廳備案號(hào):云教ICP備0901021 滇公網(wǎng)安備53010202001879號(hào) 人力資源服務(wù)許可證:(云)人服證字(2023)第0102001523號(hào)
云南網(wǎng)警備案專用圖標(biāo)
聯(lián)系電話:0871-65317125(9:00—18:00) 獲取招聘考試信息及咨詢關(guān)注公眾號(hào):hfpxwx
咨詢QQ:526150442(9:00—18:00)版權(quán)所有:易賢網(wǎng)
云南網(wǎng)警報(bào)警專用圖標(biāo)