web性能優(yōu)化

Web篇之JS性能優(yōu)化

首先搓译,性能優(yōu)化分好幾個(gè)方面悲柱,本章我們從js方面來(lái)優(yōu)化锋喜。

1:垃圾收集


日常中的某些情況下垃圾收集器無(wú)法回收無(wú)用變量些己,導(dǎo)致的一個(gè)結(jié)果就是——內(nèi)存使用率不斷增高,以下為對(duì)應(yīng)的情況以及處理方法嘿般。


①對(duì)象相互引用會(huì)導(dǎo)致引用計(jì)數(shù)始終為2怒详,所以用完對(duì)象后應(yīng)將引用設(shè)為null抖格,例子如下

letelement = document.getElementById("test");letmyObject =new Object();

myObject.element = element;

element.someObject = myObject;

//....用完后需要加如下代碼

myObject.element = null;

element.someObject = null;

②當(dāng)數(shù)據(jù)不再有用時(shí),需要通過(guò)將值設(shè)為null來(lái)解除引用,該做法適用于大多數(shù)全局變量和全局對(duì)象屬性翁脆,例子如下

function createPerson(name){

? ? let localPerson =new Object();

? ? localPerson.name = name;

? ? return localPerson

}

let globalPerson = createPerson("test")//...用完后手動(dòng)解除globalPerson =null

③關(guān)于與閉包相關(guān)的內(nèi)存泄漏如下

function assignHandler(){

? let element = document.getElementById("test");

? element.onclick =function(){

? ? alert(element.id)? ?

? }? ? ? ? ?

}//以上會(huì)導(dǎo)致element的引用數(shù)無(wú)法被回收,更改如下function assignHandler(){

? let element = document.getElementById("test");

? let id = element.id;

? element.onclick =function(){

? ? alert(id)

? }? ? ? ? ?

? element =null;?

}

2:事件委托

在js中,添加到頁(yè)面上的事件處理程序數(shù)量會(huì)直接關(guān)系到頁(yè)面整體運(yùn)行運(yùn)行性能。導(dǎo)致這一問(wèn)題的原因是多方面的派任。首先函數(shù)都是對(duì)象,都會(huì)占用內(nèi)存璧南;內(nèi)存中對(duì)象越多掌逛,性能就越差。其次司倚,必須事先指定所有事件處理程序而導(dǎo)致的DOM訪(fǎng)問(wèn)次數(shù)豆混,會(huì)延遲整個(gè)頁(yè)面的交互就緒時(shí)間。以下為對(duì)應(yīng)的情況以及處理方法

①同類(lèi)型的事件處理函數(shù)過(guò)多時(shí)动知,應(yīng)該結(jié)合為一個(gè)皿伺,例子如下:

//html代碼

    ? ?
  • Go somewhere
  • ? ?
  • Say hi
//分別加上事件處理-JS代碼

let item1 = document.getElementById("goSomeWhere");

let item2 = document.getElementById("sayHi");

EventUtil.addHandler(item1, "click",function(event){

? console.log("goSomeWhere")?

}

EventUtil.addHandler(item2, "click",function(event){

? console.log("sayHi");?

}//改善點(diǎn)即將click事件結(jié)合在一起let list = document.getElementById("myLinks")

EventUtil.addHandler(list, "click",function(event){

? event = EventUtil.getEvent(event);

? let target = EventUtil.getTarget(event);


? switch(target.id){

? ? case"goSomeWhere":

? ? ? console.log("goSomeWhere");

? ? ? break;

? case"sayHi":

? ? ? console.log("sayHi");? ?

? ? ? break;? ? ? ? ? ?

? }? ?

}

②內(nèi)存留有過(guò)時(shí)不用的“空事件處理程序”也是造成性能問(wèn)題的主因,兩種情況下會(huì)造成該問(wèn)題盒粮。運(yùn)用removeChild()和replaceChild()方法去除節(jié)點(diǎn)時(shí)鸵鸥;在使用innerHTML替換頁(yè)面某一部分時(shí),如果帶有事件處理程序的元素被innerHTML刪除了拆讯,那么原有事件處理函數(shù)極有可能無(wú)法被回收脂男,例子如下

//例子中id為myBtn的點(diǎn)擊事件變?yōu)榱丝帐录幚沓绦? ? let btn = document.getElementById("myBtn");

? ? btn.onclick =function(){

? ? ? document.getElementById("myDiv").innerHTML = "xxxx";?

? ? };//改善點(diǎn)即需要手工移除事件處理程序? ? let btn = document.getElementById("myBtn");

? ? btn.onclick =function(){

? ? ? btn.onclick =null;

? ? ? document.getElementById("myDiv").innerHTML = "xxxx";?

? ? };

3:注意作用域

關(guān)于作用域鏈,我們明白訪(fǎng)問(wèn)全局變量會(huì)比訪(fǎng)問(wèn)局部變量要慢

①若某處循環(huán)使用全局變量時(shí)种呐,我們可以略做修改宰翅,例子如下

//假設(shè)有多個(gè)img標(biāo)簽的內(nèi)容,循環(huán)中引用了多次document全局變量function updateUI(){

? let imgs = document.getElementsByTagName("img")

? for(let i = 0; len = imgs.length; i < len; ++i){

? ? imgs[i].title = document.title + " image “ + i?

? }? ?

? let msg = document.getElementById("msg");

? msg.innerHTML = "Update";? ?

}

//改善點(diǎn)

function updateUI(){

? let doc = document

? let imgs = doc.getElementsByTagName("img")

? for (let i = 0; len = imgs.length; i < len; ++i){

? ? imgs[i].title = doc.title + " image “ + i?

? }? ?

? let msg = doc.getElementById("msg");

? msg.innerHTML = "Update";? ?

}

②盡量少用with爽室,因?yàn)閣ith會(huì)增加其中執(zhí)行代碼的作用域鏈的長(zhǎng)度

4:選擇正確方法

首先汁讼,我們要了解JS中算法的復(fù)雜度

標(biāo)記名稱(chēng)?描述

O(1)常數(shù)不管有多少值,執(zhí)行的時(shí)間都是恒定的阔墩。一般表示簡(jiǎn)單值和存儲(chǔ)在變量中的值

O(log n)對(duì)數(shù)總的執(zhí)行時(shí)間和值的數(shù)量相關(guān)嘿架,但是要完成算法并不一定要獲取每個(gè)值。例如:二分查詢(xún)

O(n) 線(xiàn)性總執(zhí)行時(shí)間和值的數(shù)量直接相關(guān)啸箫。例如:遍歷某個(gè)數(shù)組中的所有元素

O(n^2)平方總執(zhí)行時(shí)間和值的數(shù)量有關(guān)耸彪,每個(gè)值至少要獲取n次。例如:插入排序

常數(shù)值和訪(fǎng)問(wèn)數(shù)組元素操作都是O(1)操作忘苛;對(duì)象屬性查找操作是O(n)操作蝉娜;

let values =? [5, 10]; let sum = values[0] + values[1]屬于O(1)操作;let values = window.location.href屬于O(2)操作

①遇到有多次屬性查詢(xún)的場(chǎng)合扎唾,可以考慮是否能做優(yōu)化召川,例子如下

//這里總共做了6次屬性查詢(xún),其中window.location.href.substring與window.location.href.indexOf分別為3次let query = window.location.href.subsring(window.location.href.indexOf("?"))//改善, 第一次訪(fǎng)問(wèn)時(shí)復(fù)雜度會(huì)是O(n),但該版本只有4次屬性查詢(xún)胸遇,相對(duì)于原始版本節(jié)省了33%let url = window.location.href;

let query = url.substring(url.indexOf("?"));

②循環(huán)優(yōu)化荧呐,這里其實(shí)用后測(cè)試循環(huán)代替前測(cè)試循環(huán)會(huì)更好,不過(guò)本地不采用,例子如下

//原有復(fù)雜度為O(n)for(let i = 0; i < values.length; ++i){

? process(values[i]);?

}//更改后復(fù)雜度為O(1)for(let i = values.length - 1; i >= 0; --i){

? process(values[i])?

}

③最小化語(yǔ)句數(shù)相關(guān)

例如進(jìn)行多個(gè)聲明時(shí)倍阐,我們可以進(jìn)行組合概疆,例子如下

//多個(gè)聲明

let count = 5;

let color = "blue";

let values = [1, 2, 3];//組合成一個(gè)let count = 5峰搪,

? ? color = ”blue",

? ? values = [1, 2, 3]

例如插入迭代值時(shí)届案,例子如下

//修改前

let name = values[i];

i++;//修改后let name = values[i++]

使用數(shù)組和對(duì)象字面量時(shí),例子如下

//修改前

let values =new Array();

values[0] = 123;

values[1] = 456;

values[2] = 789;

let person =new Object();

person.name = "Eric";

person.age = 20;//修改后let values = [123, 456, 789]

let person = {

? name: "Eric",

? age:20,? ?

}

④創(chuàng)建DOM節(jié)點(diǎn)最好使用innerHTML方法罢艾,因?yàn)閕nnerHTML設(shè)置值時(shí)楣颠,后臺(tái)會(huì)創(chuàng)建HTML解析器,然后使用內(nèi)部的DOM調(diào)用來(lái)創(chuàng)建DOM結(jié)構(gòu)咐蚯,而非基于JS的DOM調(diào)用童漩。

調(diào)用一次innerHTML,就會(huì)進(jìn)行一次現(xiàn)場(chǎng)刷新春锋,循環(huán)插入DOM結(jié)構(gòu)時(shí)矫膨,應(yīng)注意盡量調(diào)用少次數(shù)的innerHTML,代碼如下

//錯(cuò)誤方法期奔,做了很多次現(xiàn)場(chǎng)刷新

let list = document.getElementById("myList"),

? ? i;for(i = 0; i < 10; ++i){

? list.innerHTML = html+= "

  • Item " + i + "
  • "?

    }//正確方法侧馅,盡管在字符串連接上有性能損失,但卻只做了一次現(xiàn)場(chǎng)刷新let list = document.getElementById("myList"),

    ? ? html = "",

    ? ? i;for(i = 0; i < 10; ++i){

    ? html += "

  • Item " + i + "
  • "?

    }

    list.innerHTML = html

    ⑤其他如有多個(gè)if-else語(yǔ)句時(shí)呐萌,應(yīng)盡可能轉(zhuǎn)為Switch語(yǔ)句馁痴;用appendChild()插入元素時(shí),應(yīng)采用自上而下插入肺孤;面向?qū)ο缶幊虝r(shí)罗晕,應(yīng)合理釋放內(nèi)存,設(shè)object為null赠堵。

    ?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
    • 序言:七十年代末小渊,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子茫叭,更是在濱河造成了極大的恐慌酬屉,老刑警劉巖,帶你破解...
      沈念sama閱讀 211,042評(píng)論 6 490
    • 序言:濱河連續(xù)發(fā)生了三起死亡事件揍愁,死亡現(xiàn)場(chǎng)離奇詭異呐萨,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)吗垮,發(fā)現(xiàn)死者居然都...
      沈念sama閱讀 89,996評(píng)論 2 384
    • 文/潘曉璐 我一進(jìn)店門(mén)垛吗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)凹髓,“玉大人烁登,你說(shuō)我怎么就攤上這事。” “怎么了饵沧?”我有些...
      開(kāi)封第一講書(shū)人閱讀 156,674評(píng)論 0 345
    • 文/不壞的土叔 我叫張陵锨络,是天一觀(guān)的道長(zhǎng)。 經(jīng)常有香客問(wèn)我狼牺,道長(zhǎng)羡儿,這世上最難降的妖魔是什么? 我笑而不...
      開(kāi)封第一講書(shū)人閱讀 56,340評(píng)論 1 283
    • 正文 為了忘掉前任是钥,我火速辦了婚禮掠归,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘悄泥。我一直安慰自己虏冻,他們只是感情好,可當(dāng)我...
      茶點(diǎn)故事閱讀 65,404評(píng)論 5 384
    • 文/花漫 我一把揭開(kāi)白布弹囚。 她就那樣靜靜地躺著厨相,像睡著了一般。 火紅的嫁衣襯著肌膚如雪鸥鹉。 梳的紋絲不亂的頭發(fā)上蛮穿,一...
      開(kāi)封第一講書(shū)人閱讀 49,749評(píng)論 1 289
    • 那天,我揣著相機(jī)與錄音毁渗,去河邊找鬼践磅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛灸异,可吹牛的內(nèi)容都是我干的音诈。 我是一名探鬼主播,決...
      沈念sama閱讀 38,902評(píng)論 3 405
    • 文/蒼蘭香墨 我猛地睜開(kāi)眼绎狭,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼细溅!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起儡嘶,我...
      開(kāi)封第一講書(shū)人閱讀 37,662評(píng)論 0 266
    • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喇聊,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后蹦狂,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體誓篱,經(jīng)...
      沈念sama閱讀 44,110評(píng)論 1 303
    • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
      茶點(diǎn)故事閱讀 36,451評(píng)論 2 325
    • 正文 我和宋清朗相戀三年凯楔,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了窜骄。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
      茶點(diǎn)故事閱讀 38,577評(píng)論 1 340
    • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡摆屯,死狀恐怖邻遏,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤准验,帶...
      沈念sama閱讀 34,258評(píng)論 4 328
    • 正文 年R本政府宣布赎线,位于F島的核電站,受9級(jí)特大地震影響糊饱,放射性物質(zhì)發(fā)生泄漏垂寥。R本人自食惡果不足惜,卻給世界環(huán)境...
      茶點(diǎn)故事閱讀 39,848評(píng)論 3 312
    • 文/蒙蒙 一另锋、第九天 我趴在偏房一處隱蔽的房頂上張望滞项。 院中可真熱鬧,春花似錦夭坪、人聲如沸蓖扑。這莊子的主人今日做“春日...
      開(kāi)封第一講書(shū)人閱讀 30,726評(píng)論 0 21
    • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)律杠。三九已至,卻和暖如春竞惋,著一層夾襖步出監(jiān)牢的瞬間柜去,已是汗流浹背。 一陣腳步聲響...
      開(kāi)封第一講書(shū)人閱讀 31,952評(píng)論 1 264
    • 我被黑心中介騙來(lái)泰國(guó)打工拆宛, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留嗓奢,地道東北人。 一個(gè)月前我還...
      沈念sama閱讀 46,271評(píng)論 2 360
    • 正文 我出身青樓浑厚,卻偏偏與公主長(zhǎng)得像股耽,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子钳幅,可洞房花燭夜當(dāng)晚...
      茶點(diǎn)故事閱讀 43,452評(píng)論 2 348

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