摘要:可維護解耦采用引入文件的方式取代在頁面寫代碼避免在中創建大量當用于插入數據時,盡量不要直接插入標記。簡化循環體循環體是執行最多的,所以要確保其被最大限地優化,確保沒有某些可以被很容易移除循環的密集計算。
可維護 解耦HTML/JavaScript
1、采用引入js文件的方式取代在html頁面寫js代碼
2、避免在js中創建大量html
(1)當js用于插入數據時,盡量不要直接插入標記。一般可以在頁面中直接包含并隱藏標記,然后等到整個頁面渲染好之后,就可以用js顯示該標記,而非生成它
(2)也可以通過Ajax請求獲得更多要顯示的html,這個方法可以讓同樣的渲染層(PHP、JSP、Ruby等等)來輸出標記,而不是直接嵌在js中
盡量不要在js中更改樣式,而是采用動態更改樣式類,從而做到對于樣式的問題應只查看CSS文件來解決,例:
element.style.color = "red"; element.style.backgroundColor = "blue"; 更改后: element.className = "edit";解耦應用邏輯/事件處理程序
每個web應用一般都有相當多的事件處理程序,監聽這無數不同的事件,然而,很少有能仔細得將應用邏輯從事件處理程序中分離的,如下:
function handleKeyPress (event) { if(event.keyCode == 1){ let target = event; let value = 5 * parseInt(target.value); if(value > 10){ document.getElementById("tip-msg").style.display = "block"; } } }
這個事件處理程序處理包含了應用邏輯,還進行了事件處理,這種方式的問題有其雙重性
(1)、處理通過事件之外就沒有辦法執行應用邏輯
(2)、調試困難,如果沒有發生預想的結果,并不知道是事件沒被調用還是應用邏輯失敗
(3)、如果后續的事件需要執行相同的應用邏輯,那么就必須復制功能代碼或將代碼抽到一個多帶帶的函數中所以就好進行兩者的解耦,即一個事件處理程序應該從事件對象中提取相關信息,并將這些信息傳送到處理應用邏輯的某個方法中,前面例子重寫如下:
function validateValue (value) { value = 5 * parseInt(value); if(value > 10){ document.getElementById("tip-msg").style.display = "block"; } } function handleKeyPress (event) { if(event.keyCode == 13){ let target = event; validateValue(target.value); } }
從而使validateValue()中沒有任何東西會依賴于任何事件處理程序邏輯,他只接收一個值,并根據該值進行其他處理
好處:如果事件最初只有鼠標事件觸發,那么現在只需少量修改就可以實現按鍵觸發
最多創建一個全局變量,讓其他對象和函數存在其中,如:
//兩個全局變量——避免!! let name= "bad"; function sayName() { alert(name); } //一個全局變量——推薦 let good = { name: "nice", sayName: function () { alert(this.name); } }
多人協作開發可以使用命名空間
//創建全局對象 let wrox = {}; //為Tony創建命名空間 wrox.Tony = {}; //為Tony(可以以人名劃分)創建方法 wrox.Tony.sayName = function () { ... };
上述例子,wrox是全局變量,其他命名空間在此之上創建,只要所有人都按這樣寫,那么就不用當心不同開發者創建相同的方法等,因為它存在于不同的命名空間
避免與null進行比較應該讓條件與預想的類型進行比較而不是與null
//bad function sortArray(values) { if(values != null){ ... } } //good function sortArray(values) { if(values instanceof Array){ ... } }抽離常量
const constants = { INVALID_VALUE_MSG:"Invalid value!", INVALID_VALUE_URL:"/errors/invalid.php" }性能優化
因為訪問全局變量要比訪問局部變量慢,因為要遍歷作用域鏈,所以減少花費在作用域鏈上的時間,就可以增加腳本的整體新能
避免全局查找//bad function updateUI () { let imgs = document.getElementsByTagName("img"); for(let i=0, len=imgs.length; i使用事件代理上面將document對象保存在doc變量中,然后替換原來的document,與原來相比,只需進行一次全局查找,速度肯定更快
循環優化循環優化基本步驟如下:
1、減值迭代——大多數循環使用一個從0開始、增加到某個特定值的迭代器。在很多情況下,從最大值開始,在循環中的迭代器更加高效。
2、簡化終止條件——由于每次循環過程都會計算終止條件,所以必須保證它盡可能快。也就是說避免屬性查找或者其他O(n)的操作。
3、簡化循環體——循環體是執行最多的,所以要確保其被最大限地優化,確保沒有某些可以被很容易移除循環的密集計算。
4、使用后側試循環——最常用的for循環和while循環都是前測試循環。而入do—while這種后側試循環,可以避免最初終止條件的計算//基本for循環 for(let i=0;i最小語句數=0; i--){ process(values[i]); } //再進行改造成后測試循環,此處主要的優化是將終止條件和自減操作符組合成了單個語句 let i = values.length - 1; if(i> -1){ do{ process(valeus[i]); }while(--i>=0) } 1、多個聲明變量
//bad let count = 5; let color = "blue"; let values = [1,2,3]; let now = new Date(); //good let count = 5, color = "blue", values = [1,2,3], now = new Date();2、插入迭代值
//bad let name = values[i]; i++; //good let name = values[i++];3、使用數組和對象字面量
//bad let values = new Array(); values[0] = 123; values[1] = 456; values[2] = 789; //bad let person = new Object(); person.name = "Tony"; person.age = 18; person.sayName = function () { alert(this.name); } //good let values = [123,456,789]; let person = { name: "Tony", age: 18, sayName: function () { alert(this.name); } }優化DOM交互1、最小現場更新
//bad let list = document.getElementById("myList"), item, i; for(i=0; i<10; i++){ item = document.createElement("li"); list = appendChilde(item); item.appendChild(document.createTextNode("Item" + i); }上述代碼為列表添加了10個項目,每添加個項目時,都有2個現場更新:一個添加元素,另一個給他添加文本節點,這樣添加10個項目,這個操作總共要完成20個現場更新。
解決方法:
1、將列表從頁面上移除,最后進行更新,最后在將列表插回到同樣的位置,看似很美好,但這樣做會導致在每次更新的時候它會不必要的閃爍
2、使用文檔碎片來構建DOM結構,接著將其添加到list元素中,這個方式避免了閃爍,如下://good,只有一次現場更新 let list = document.getElementById("myList"); framgent = document.createDocumentFragment(), itme, i; for(i=0; i<10; i++){ item = document.createElement("li"); fragment.appendChild(item); item.appendChild(document.createTextNode("Item" + i)); } list.appendChild(fragment);2、使用innerHTML
有兩種方式在頁面上創建DOM節點:使用諸如createElement()和appendChild()之類的DOM方法,以及使用innerHTML。對于小的DOM而言,兩者效率差不多,對于大的DOM改動,使用innerHTML要快得多。
原因:當把innerHTML設置為某個值時,后臺會創建一個HTML解析器,然后使用內部的DOM調用來創建DOM結構,而非基于js的DOM調用,由于內部方法是編譯好的而非解釋執行的,所以執行快得多,所以上面例子還可以優化let list = document.getElementById("myList"), html = "", i; for(i=0; i<10; i++){ html += `Item${i} `; } list.innerHTML = html; //tip同樣要避免多次調用innerHTML,即要做到構建好一個字符串然后一次性調用innerHTML
頁面上的事件處理程序的數量和頁面的響應用戶交互的速度之間是負相關的
任何冒泡的事件都不僅僅可以在事件的目標上進行處理,目標的任何祖先節點上也能處理,如果可能,在文檔級別附加事件處理程序,這樣就可以處理整個頁面的事件
任何時候要訪問HTMLCollection,不管是一個屬性還是一個方法,都是在文檔上進行的一個查詢,這個查詢開銷很昂貴,爾等消費不起
let images = document.getElementsByTagName("img"); imags, i, len; for(i=0; len=images.length; itip:發生以下情況會返回HTMLCollection對象:
展開循環(Duff)
(1)、進行了對getElementsByTagName()的調用;
(2)、獲取了元素的childNodes屬性;
(3)、獲取了元素的attribute屬性;
(4)、訪問了特殊的集合,如document.forms、document.images等當循環的次數是確定的,消除循環并使用多次函數調用往往更快,
//low for(let i=0;i<3;i++){ process(values[i]); } //fast,消除建立循環和處理終止條件的額外開銷 process(values[0]); process(values[1]); process(values[2]);如果迭代次數事項不能確定,可以使用Duff裝置的技術
Duff:通過計算迭代的次數是否為8的倍數將一個循環展開為一系列語句let iterations = Math.ceil(values.length / 8); //向上取整確保結果是整數 let startAt = values.length % 8; //獲取無法通過上面進行處理的項,如果values.length為10,那么startAt為2 let i = 0; do { switch(startAt) { case 0: process(values[i++]); case 7: process(values[i++]); case 6: process(values[i++]); case 5: process(values[i++]); case 4: process(values[i++]); case 3: process(values[i++]); case 2: process(values[i++]); case 1: process(values[i++]); } startAt = 0; } while (--iterations > 0);上面運行的結果是先運行startAt次的process(),然后startAt設置為0,后面循環都執行8次process(),展開循環可以提升大數據集的處理速度。
將do-while循環分成2個多帶帶的循環可以讓Duff更快let iterations = Math.ceil(values.length / 8); //向上取整確保結果是整數 let startAt = values.length % 8; //獲取無法通過上面進行處理的項,如果values.length為10,那么startAt為2 let i = 0; if(leftover > 0){ do{ process(values[i++]); } while (--leftover > 0); } do { process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); process(values[i++]); } while (--iterations > 0);上面代碼讓剩余的計算部分不會在實際循環中處理,而是在一個初始化循環中進行除以8的操作,當處理掉了額外的元素,繼續執行每次調用8次process()的主循環,這個方法幾乎比原始的Duff裝置快40%
其他性能優化注意事項
tip:以上只適用于處理大數據集下面并非主要影響性能的主要問題,應用得當,會有相當大的提升
1、原生方法較快——只要有可能,使用原生方法而不是自己用js重寫一個,因為原生方法是用注入C/C++之類的編譯型語言寫出來的,所以要比js快得多,比如要用Math對象的數學運算
2、Swithc語句較快——如果有一系列復雜的if-else語句,可以轉換成單個switch語句則可以得到更快的代碼,還可以通過將case語句按照最可以能的到最不可能的順序進行組織,來進一步優化switch語句。
3、位運算符較快——當進行數學運算時,位運算符操作要比任何布爾運算或者算數運算快,諸如取模,邏輯與和邏輯或都可以考慮用位運算替換以上內容參考自《JavaScript 高級程序設計(第三版)》
終于寫完了(~ ̄▽ ̄)~
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://m.specialneedsforspecialkids.com/yun/99157.html
摘要:前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。對該漏洞的綜合評級為高危。目前,相關利用方式已經在互聯網上公開,近期出現攻擊嘗試爆發的可能。 前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點;分為新聞熱點、開發教程、工程實踐、深度閱讀、開源項目、巔峰人生等欄目。歡...
摘要:谷歌,,,雅虎和最近因世界杯獲得龐大觀眾數量的都在使用。因此,數據庫服務器的能力是毋庸置疑的。微軟的服務器,服務器以及未來的更新價格昂貴。更依賴于微軟數量有限的開發者做出的改進和更新。 【編者按】本文主要針對開源 PHP 和非開源的 ASP.NET 在性能、成本、可擴展性,技術支持和復雜性等方面進行比較。 在網上論壇,總是有成百上千的文章和帖子在討論 PHP 和 ASP.NET,究竟誰...
摘要:相反,我們將專注于將添加到用編寫的簡單應用程序中。使用創建應用程序。示例應用程序有兩個組件應用程序和。除在全球率先支持外,現已全面應用于等主流框架中。 showImg(https://segmentfault.com/img/bVbcvaQ?w=500&h=278); 概述 在本文中,我們將展示如何將WijmoJS與NPM和Webpack一起使用來創建最流行的基于JavaScript應...
摘要:前端每周清單第期與模式變遷與優化界面生成作者王下邀月熊編輯徐川前端每周清單專注前端領域內容,以對外文資料的搜集為主,幫助開發者了解一周前端熱點分為新聞熱點開發教程工程實踐深度閱讀開源項目巔峰人生等欄目。 showImg(https://segmentfault.com/img/remote/1460000013279448); 前端每周清單第 51 期: React Context A...
閱讀 2321·2021-09-28 09:45
閱讀 3604·2021-09-24 09:48
閱讀 2269·2021-09-22 15:49
閱讀 3105·2021-09-08 16:10
閱讀 1596·2019-08-30 15:54
閱讀 2330·2019-08-30 15:53
閱讀 3026·2019-08-29 18:42
閱讀 2877·2019-08-29 16:19