成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

[ JS 進(jìn)階 ] 如何改進(jìn)代碼性能 (3)

young.li / 2698人閱讀

摘要:這樣就改進(jìn)了代碼的性能,看代碼將保存在局部變量中所以啊,我們?cè)陂_(kāi)發(fā)中,如果在函數(shù)中會(huì)經(jīng)常用到全局變量,把它保存在局部變量中避免使用語(yǔ)句用語(yǔ)句延長(zhǎng)了作用域,查找變量同樣費(fèi)時(shí)間,這個(gè)我們一般不會(huì)用到,所以不展開(kāi)了。

  

本來(lái)在那片編寫(xiě)可維護(hù)性代碼文章后就要總結(jié)這篇代碼性能文章的,耽擱了幾天,本來(lái)也是決定每天都要更新一篇文章的,因?yàn)橐郧扒废绿鄸|西沒(méi)總結(jié),學(xué)過(guò)的東西沒(méi)去總結(jié)真的很快就忘記了,記錄一下在你腦力留下更深的印象,特別是這些可維護(hù)性代碼,性能什么的,當(dāng)在你腦子里形成一種習(xí)慣了,那你就牛了!這里也要給初學(xué)者一個(gè)建議:多總結(jié)你學(xué)過(guò)的東西,因?yàn)檫@其實(shí)也是在學(xué)習(xí)新知識(shí)! 好,進(jìn)入我們的主題:如何提高JS代碼的性能。

在今天的web應(yīng)用中,應(yīng)用了大量的Javascript,因此代碼的執(zhí)行效率變得尤為重要,也就是性能!為了提高JS的性能,我們應(yīng)該掌握一些基本的性能優(yōu)化方式,并讓它成為我們書(shū)寫(xiě)代碼的習(xí)慣。下面介紹幾種優(yōu)化性能的方式,很多初學(xué)者甚至有經(jīng)驗(yàn)的開(kāi)發(fā)者也會(huì)忽略,希望對(duì)你有幫助!

1.優(yōu)化DOM交互

DOM與我們的頁(yè)面緊密相關(guān),瀏覽器渲染頁(yè)面也就是在渲染解析后的DOM元素,DOM操作與交互要消耗大量的時(shí)間,因?yàn)樗鼈兺枰匦落秩菊麄€(gè)頁(yè)面或者一部分。進(jìn)一步說(shuō),看似細(xì)微的一些操作也可能需要花很多時(shí)間來(lái)執(zhí)行,因?yàn)?b>DOM要處理的信息非常多,因此我們應(yīng)該盡可能地優(yōu)化與DOM相關(guān)的操作,加快瀏覽器對(duì)頁(yè)面的渲染!為什么有些DOM操作會(huì)影響頁(yè)面性能,可以查看我寫(xiě)的一些關(guān)于瀏覽器原理的文章:

ok,優(yōu)化DOM操作,我們主要有一些幾種方式:

1.1 最小化現(xiàn)場(chǎng)更新

什么是DOM的現(xiàn)場(chǎng)更新:需要對(duì)DOM部分已經(jīng)顯示的頁(yè)面的一部分的顯示立即更新。但是,每一個(gè)更改,不管是插入單個(gè)字符,還是一處整個(gè)片段,都有一定的性能懲罰,因?yàn)闉g覽器需要重新計(jì)算無(wú)數(shù)尺寸以進(jìn)行更新(相關(guān)知識(shí)請(qǐng)閱讀:)。所以,現(xiàn)場(chǎng)更新進(jìn)行的越多,代碼執(zhí)行所花的時(shí)間就越長(zhǎng),反之代碼執(zhí)行越快,如下:

var list = document.getElementById("mylist"),
           item,
           i;
for(i = 0; i < 10; i++){
    item = document.creatElement("li");
    list.appendChild(item);
    item.appendChild(document.creatTextNode("item" + i));
}

這段代碼為列表mylist添加了10個(gè)項(xiàng)目,沒(méi)添加一個(gè)項(xiàng)目都要進(jìn)行2次的現(xiàn)場(chǎng)更新:添加元素和添加文本節(jié)點(diǎn),所以這個(gè)操作一個(gè)需要完成20個(gè)現(xiàn)場(chǎng)更新,每個(gè)更新都會(huì)損失性能,可見(jiàn)這樣的代碼運(yùn)行起來(lái)是相對(duì)緩慢的。

解決的方法是使用文檔碎片間接地更改DOM元素:

var list = document.getElementById("mylist"),
           fragment = document.creatDocumentFragment(),
           item,
           i;
for(i = 0; i < 10; i++){
    item = document.creatElement("li");
    fragment .appendChild(item);
    item.appendChild(document.creatTextNode("item" + i));
}
list.appendChild(fragment);

像這樣的代碼只需進(jìn)行一次的現(xiàn)場(chǎng)更新。記住,當(dāng)給appendChild()傳入文檔碎片是,只有文檔碎片中的子節(jié)點(diǎn)才會(huì)被添加到目標(biāo)元素,碎片本身不會(huì)被添加。

現(xiàn)在,你應(yīng)該明白你用循環(huán)直接進(jìn)行DOM節(jié)點(diǎn)的增刪查改是多么對(duì)不起瀏覽器的事了吧 `(∩_∩)′ 。

1.2 使用 innerHTML

除了上面代碼中使用的creatElement()appendChild()結(jié)合的方法創(chuàng)建DOM元素之外,還有通過(guò)給innerHTML賦值來(lái)創(chuàng)建。對(duì)于小的DOM更改而言,兩種方法的效率其實(shí)差不多,但對(duì)于大量的DOM節(jié)點(diǎn)的更改,后者要比前者快得多!為啥捏?

因?yàn)楫?dāng)我們給innerHTML賦值時(shí),后臺(tái)會(huì)創(chuàng)建一個(gè)HTML解析器,然后使用內(nèi)部的DOM調(diào)用來(lái)創(chuàng)建DOM結(jié)構(gòu),而非基于JavascriptDOM調(diào)用,由于內(nèi)部方法是編譯好的而非解釋執(zhí)行的,所以執(zhí)行代碼的速度要快很多!

innerHTML改寫(xiě)上面的例子:

   var list = document.getElementById("mylist"),
              html = "", //聲明一個(gè)空字符串
               i;
    for(i = 0; i < 10; i++){
        html += "
  • item" + i + "
  • "; } list.innerHTML = html; // 這里記得innerHTML后面的HTML四個(gè)字母都要大寫(xiě)!

    這種方式同樣也只進(jìn)行了一次的現(xiàn)場(chǎng)更新,并且性能要比上一種方式要好!雖然在字符串的鏈接上有點(diǎn)性能損失。

    1.3 使用事件代理/事件委托

    事件處理程序?yàn)?b>web應(yīng)用提供交互能力,因此許多開(kāi)發(fā)人員會(huì)不分青紅皂白地向頁(yè)面中添加大量的處理程序,有個(gè)問(wèn)題就是一個(gè)頁(yè)面上的事件處理程序數(shù)量將直接關(guān)系到頁(yè)面的整體運(yùn)行性能。為什么捏?

    首先,事件處理程序?qū)?yīng)至少一個(gè)函數(shù),JS中每個(gè)函數(shù)都是對(duì)象,都會(huì)占用內(nèi)存,內(nèi)存中的對(duì)象越多,性能就越差。

    其次,我們必須事先指定所有事件處理程序,這就導(dǎo)致了DOM訪問(wèn)次數(shù)增多,會(huì)延遲整個(gè)頁(yè)面的交互就緒時(shí)間,頁(yè)面響應(yīng)用戶操作變得相對(duì)緩慢。

    所以減少事件處理程序同樣也可以讓我們的頁(yè)面更牛暢!使用事件委托勢(shì)在必得??!

    事件委托的原理其實(shí)就是事件冒泡,只指定一個(gè)事件處理程序就可以管理某一類型操作的所有事件。例如:click事件會(huì)一直冒泡到document層次,也就是說(shuō)我們不必為每個(gè)元素添加事件,只需在較高的層次的元素上添加事件處理程序即可,然后利用事件對(duì)象(event)的屬性或方法去判斷當(dāng)前點(diǎn)擊的元素,然后做出相應(yīng)的響應(yīng)。這個(gè)我就不展開(kāi)講了,初學(xué)者可以自行查閱事件冒泡知識(shí)。

    2.作用域很重要

    說(shuō)到作用域啊就很容易想到作用域鏈(scope chain),我們知道要搜索一個(gè)變量,所在的執(zhí)行環(huán)境都要沿著這條作用域向上搜索這個(gè)變量,作用域鏈上有很多的變量,那么我們就得遍歷,遍歷就需要時(shí)間啊,而且你越往上查找所需時(shí)間越多,如果我們能減少這個(gè)時(shí)間,我們代碼執(zhí)行效率不是可以提高了嗎?

    好聰明啊,ok,我看看有哪些方式可以減少這個(gè)時(shí)間:

    2.1 避免全局查找

    這是性能優(yōu)化的一重點(diǎn),上面也說(shuō)了,越往上查找時(shí)間越多,也就是說(shuō)查找全局變量和函數(shù)比局部要多!看代碼:

    function updateUI(){
        var imgs = document.getElementByTagName("img");
        for(var i = 0 ,lng = imgs.length;i < lng;i ++){
            imgss[i].title = document.title + "image" + i;
        }
        var msg = docuement.getElementById("msg");
        msg.innerHTML = "update complete.";
    }
    

    這代碼很正常呀!我之前也經(jīng)常這么做滴。但是我們細(xì)心可以發(fā)現(xiàn),這段代碼有三處引用了全局變量document,如果我們的頁(yè)面很多圖片,那么在for循環(huán)中的document就會(huì)被執(zhí)行上百次,而每次都要需要在作用域鏈中查找,時(shí)間都去哪了,我還沒(méi)......停!。

    我們可以通過(guò)在函數(shù)中創(chuàng)建一個(gè)局部變量保存對(duì)document的引用,這樣,我們?cè)诤瘮?shù)里任何地方引用document都不用跑到全局變量去找了。這樣就改進(jìn)了代碼的性能,看代碼:

    function updateUI(){
        var doc = document; // 將document保存在局部變量doc中
        var imgs = doc.getElementByTagName("img");
        for(var i = 0 ,lng = imgs.length;i < lng;i ++){
            imgss[i].title = doc.title + "image" + i;
        }
        var msg = doc.getElementById("msg");
        msg.innerHTML = "update complete.";
    }
    

    所以啊,我們?cè)陂_(kāi)發(fā)中,如果在函數(shù)中會(huì)經(jīng)常用到全局變量,把它保存在局部變量中!

    2.2 避免使用with語(yǔ)句

    用with語(yǔ)句延長(zhǎng)了作用域,查找變量同樣費(fèi)時(shí)間,這個(gè)我們一般不會(huì)用到,所以不展開(kāi)了。解決方法還是和上面的例子一樣,將全局變量保存在局部變量中!

    3.優(yōu)化循環(huán)

    循環(huán)在編程中可謂家常便飯,在js中也隨處可見(jiàn),循環(huán)體會(huì)反復(fù)地執(zhí)行同一段代碼,執(zhí)行時(shí)間一直累加,所以能夠?qū)ρh(huán)體的代碼進(jìn)行優(yōu)化也可以大大減少執(zhí)行時(shí)間!如何優(yōu)化?四種方式。

    3.1 減值迭代

    我們寫(xiě)迭代器(循環(huán)條件)的時(shí)候一般都這樣(var i = 0;i < 10;i ++),從0開(kāi)始,增加到某個(gè)特定值。然而在很多情況下,如果在循環(huán)中使用減值迭代器效率更高。我測(cè)試了下,如果循環(huán)體不復(fù)雜的話,兩者差不多!

    //增值迭代 --效率較低
    for(var i = 0;i < items.length;i++){
       doSomething(items[i]); 
    }
    //減值迭代 --效率較高
    for(var i = items.length - 1;i >= 0;i--){
       doSomething(items[i]); 
    }
    
    3.2 簡(jiǎn)化終止條件

    由于每次循環(huán)都會(huì)計(jì)算終止條件,所以必須保證它的執(zhí)行盡可能地塊。這里主要是避免其他DOM元素及其屬性的的查找。

     //看終止條件,每次循環(huán)都需要查詢items及其length屬性
    for(var i = 0;i < items.length;i++){
       doSomething(items[i]); 
    }
    
    //將items.length的值保存在局部變量lng中。
    for(var i = 0,lng = items.length;i < lng;i++){
       doSomething(items[i]); 
    }
    
    3.3 簡(jiǎn)化循環(huán)體

    原因和上面以上的,所以在循環(huán)體內(nèi)避免大量的密集的操作。

    這其實(shí)和上面講的:1.1 最小化現(xiàn)場(chǎng)更新 。是一樣的優(yōu)化方式??梢缘够厝タ纯?。

    4.基本的算法優(yōu)化

    在計(jì)算機(jī)中,算法的復(fù)雜度用O表示。下面是javascript中幾種常見(jiàn)的算法類型:

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

    O(log n):對(duì)數(shù),總的執(zhí)行時(shí)間和數(shù)量有關(guān),但不一定要獲取每一個(gè)值,如:二分法查找

    O(n) :線性,總執(zhí)行時(shí)間和數(shù)量直接相關(guān),如:遍歷

    O(n*n) :平方,總執(zhí)行時(shí)間和數(shù)量有關(guān),每個(gè)值至少獲取N次,如:插入排序

    ok,有了上面的知識(shí),我們就可以對(duì)javascript進(jìn)行一些算法上的優(yōu)化了。看代碼:

    var value = 5;
    var sum = value + 10;
    alert(sum);
    

    這段代碼進(jìn)行了4次常量值的查找:數(shù)字5,變量value,數(shù)字10,變量sum,這段代碼的算法復(fù)雜度就是O(1)。又如:

    var value = [10,5];
    var sum = value[0] + value[1];
    alert(sum);
    

    在javascript中訪問(wèn)數(shù)組元素也是一個(gè)O(1)操作,和簡(jiǎn)單的變量查找效率一樣。再看:

    var value = {one:10,two:10};
    var sum = value.one + value.two;
    alert(sum);
    

    要表達(dá)的是訪問(wèn)對(duì)象上的屬性要比訪問(wèn)數(shù)組和變量的效率低。因?yàn)檫@是一個(gè)O(n)操作。你需要在對(duì)象的原型鏈中查找該屬性,所花時(shí)間較多。

    好了,看完這個(gè)是不是感覺(jué)眼前一片光明啊。其實(shí)我們前面所講的要把經(jīng)常用到的全局屬性保存在一個(gè)局部變量中就是根據(jù)這個(gè)原理了,訪問(wèn)全局屬性是一個(gè)O(n)的操作,而訪問(wèn)變量是一個(gè)O(1)的操作,大聲告訴我,挖掘機(jī)哪家強(qiáng)??!

    5.最小化語(yǔ)句數(shù)

    前面講的優(yōu)化差不多都是和精簡(jiǎn)優(yōu)化語(yǔ)句有關(guān)的,是的,我覺(jué)得代碼的質(zhì)量和數(shù)量就是性能的評(píng)判標(biāo)準(zhǔn)。前面講了一些代碼質(zhì)量相關(guān)的優(yōu)化,這里就講講代碼數(shù)量的優(yōu)化。

    5.1 精簡(jiǎn)變量聲明
    //用了5條語(yǔ)句聲明5個(gè)變量
    var count = 5;
    var color = "red";
    var values = [1,2,3];
    var now = new Date();
    
    //用了1條語(yǔ)句聲明5個(gè)變量,注意每個(gè)變量用逗號(hào)隔開(kāi)
    var count = 5,
        color = "red",
        values = [1,2,3],
        now = new Date();
    
    5.2 使用數(shù)組和對(duì)象字面量
    // 創(chuàng)建兩個(gè)對(duì)象 ----不好的方式
    //one 四條語(yǔ)句
    var values = new Array();
    values[0] = 123;
    values[1] = 456;
    values[2] = 789;
    //two 四條語(yǔ)句
    var person = new Object();
    person.name = "jozo";
    person.age = 21;
    person.sayName = function(){
        alert(this.name);
    };
    // 創(chuàng)建兩個(gè)對(duì)象 ----推薦的方式
    //one 1條語(yǔ)句
    var values = [123,456,789]
    //two 1條語(yǔ)句
    var person = {
        name : "jozo",
        age : 21,
        sayName : function(){
        alert(this.name);
    };
    
    6.其他

    寫(xiě)累了,如有不正確的地方請(qǐng)指正哦,還有一些其他的優(yōu)化,下次文章繼續(xù)!

    文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

    轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85578.html

    相關(guān)文章

    • 初學(xué)者福音!可能是最適合你的Java學(xué)習(xí)路線和方法推薦。

      摘要:學(xué)習(xí)完多線程之后可以通過(guò)下面這些問(wèn)題檢測(cè)自己是否掌握,下面這些問(wèn)題的答案以及常見(jiàn)多線程知識(shí)點(diǎn)的總結(jié)在這里。可選數(shù)據(jù)結(jié)構(gòu)與算法如果你想進(jìn)入大廠的話,我推薦你在學(xué)習(xí)完基礎(chǔ)或者多線程之后,就開(kāi)始每天抽出一點(diǎn)時(shí)間來(lái)學(xué)習(xí)算法和數(shù)據(jù)結(jié)構(gòu)。 我自己總結(jié)的Java學(xué)習(xí)的系統(tǒng)知識(shí)點(diǎn)以及面試問(wèn)題,已經(jīng)開(kāi)源,目前已經(jīng) 35k+ Star。會(huì)一直完善下去,歡迎建議和指導(dǎo),同時(shí)也歡迎Star: https://...

      yanest 評(píng)論0 收藏0
    • 前端學(xué)習(xí)路線

      摘要:具體來(lái)說(shuō),包管理器就是可以通過(guò)命令行,幫助你把外部庫(kù)和插件放到你的項(xiàng)目里面并在之后進(jìn)行版本升級(jí),這樣就不用手工復(fù)制和更新庫(kù)。現(xiàn)在有的包管理器主要是和。 一、基礎(chǔ) 1、學(xué)習(xí)HTML基礎(chǔ) HTML給你的網(wǎng)頁(yè)賦予了結(jié)構(gòu)。它就像是人的骨架那樣讓你保持站立。首先你需要去學(xué)習(xí)語(yǔ)法以及它必須提供的一切。你的學(xué)習(xí)應(yīng)該聚焦在下面這些東西上: 學(xué)習(xí)HTML基礎(chǔ),了解如何編寫(xiě)語(yǔ)義HTML 理解如何把網(wǎng)頁(yè)分...

      FullStackDeveloper 評(píng)論0 收藏0
    • 前端學(xué)習(xí)路線

      摘要:具體來(lái)說(shuō),包管理器就是可以通過(guò)命令行,幫助你把外部庫(kù)和插件放到你的項(xiàng)目里面并在之后進(jìn)行版本升級(jí),這樣就不用手工復(fù)制和更新庫(kù)?,F(xiàn)在有的包管理器主要是和。 一、基礎(chǔ) 1、學(xué)習(xí)HTML基礎(chǔ) HTML給你的網(wǎng)頁(yè)賦予了結(jié)構(gòu)。它就像是人的骨架那樣讓你保持站立。首先你需要去學(xué)習(xí)語(yǔ)法以及它必須提供的一切。你的學(xué)習(xí)應(yīng)該聚焦在下面這些東西上: 學(xué)習(xí)HTML基礎(chǔ),了解如何編寫(xiě)語(yǔ)義HTML 理解如何把網(wǎng)頁(yè)分...

      20171112 評(píng)論0 收藏0
    • 前端進(jìn)階(14) - 如何提升前端性能和響應(yīng)速度

      摘要:一般建議文件最大不超過(guò)。按需加載可以減小首屏加載文件的體積,達(dá)到提高響應(yīng)速度的目的。如果你的項(xiàng)目不需要處理靜態(tài)資源如圖片,也不需要按需加載,并追求前端高性能的話,可以嘗試。 如何提升前端性能和響應(yīng)速度 下面大多是從前端工程化的角度給出的優(yōu)化建議,如果需要了解語(yǔ)法上的優(yōu)化,可以參考: 如何提高頁(yè)面加載速度 編寫(xiě)高效的JavaScript Web前端性能優(yōu)化進(jìn)階 - 完結(jié)篇 1. 原生...

      lylwyy2016 評(píng)論0 收藏0

    發(fā)表評(píng)論

    0條評(píng)論

    最新活動(dòng)
    閱讀需要支付1元查看
    <