摘要:第三種將原始元素拷貝到一個脫離文檔的節點中,修改副本,完成后在提貨原始元素以上脫離文檔流修改的方法推薦第二種方法。對于用展開折疊的效果,我們使用絕對定位,將其脫離文檔流,會是重繪更少些。
本文的一些注意的是我以前看書籍總結的,我們一般人寫項目時,對我們的影響并不是很大,有時完全可以忽略,但是我們知道這些總不是什么壞處。
js這個大眾語言我想,很多人多知道,它入門和簡單,可是想要深入了解還是要有一定的水平、 的,同樣的效果雖然都可以寫出來,但還是性能和可維護性卻有很大差別。下來我們就來總結一下書寫高質量js代碼的一些注意點。
代碼維護是高成本的,如果我們在開發代碼時,不注重代碼的規范,可讀性和可維護性,那么將來帶給我們的將是更大的開支。如果說你是給公司干活,自己寫完就不用管了,這樣的思想很危險。不但對他人讀取你代碼時帶來困擾,同時也是限制自己發展的一個障礙。代碼終究是要給人去閱讀的。我們整個團隊在書寫代碼時應該勁量做到:
可讀的
一致的
可預測的
看上去就像是同一個人寫的
已記錄
執行與加載管理瀏覽器中的腳本 JavaScript 代碼是個棘手的問題,因為代碼執行過程會阻塞瀏覽器的其他進程,比如用戶界面繪制,每次遇到標簽,頁面都必須停下來等待代碼下載(如果是外鏈文件)并執行,然后繼續處理其他部分,盡管如此,還是有幾種方法能減少javascript 對性能的影響。
閉合標簽之前,將所有的標簽放到頁面底部,這確保在腳本執行前頁面已加載完成了渲染。
合并腳本,頁面中的 標簽越少,加載也就也快,響應也更迅速。無論外鏈文件還是內嵌腳本都是如此
有多種無阻塞下載JavaScript方法:
使用標簽的defer屬性(H5提供一個新屬性async)
defer和async的相同點是采用并行下載,在下載過程中不會產生阻塞。區別在于執行時機,async是加載完成后自動執行,而defer需要等待頁面完成后執行。
使用動態創建元素來下載并執行代碼
使用動態創建元素不會阻塞頁面的其他進程,這樣我們可以將動態創建的放到頁面的 區域。
function(url){ var script = document.creatElement("script"); script.type = "text/javascript"; script.src = url; document.getElementsByTagName("head")[0].appendChild(script); }
我們什么時候知道腳本已經加載完成呢?Firefox,Opera,Chrome和safari3為我們提供了一個onload事件來監聽,而IE 為我們提供了onreadystatechange 事件并根據readyState屬性來進行判斷。
通過上面的方法,我們可以極大提高那些需要使用大量的JavaScript 的 web應用的實際性能
變量處理我們都知道,JavaScript通過函數管理作用域。在函數內部聲明的變量只在這個函數內部,函數外面不可用。另一方面,全局變量就是在任何函數外面聲明的或是未聲明直接簡單使用的。我們應該盡量的減少全局變量,這樣避免全局變量過多而造成變量命名沖突,同時又占用內存。
聲明變量是我們盡量用var去聲明
function fun(){ a = 1; // 這樣是不推薦的,因為a是隱式的全局變量 var b = 2; // 這樣是推薦的 var c = d = 5 // 這樣也是不推薦的,因為d是隱式的全局變量 }
減少全局變量我們還可以使用立即執行函數,下來我們也會有章節去詳細的講解
(function(){ var a = 3; var b = 4; })()
另外我們應該知道變量提升原則,這個在后面的章節中我們還會詳細的講解我們在寫一些變量時,可以這樣去寫。
function(){ var a, b, c; a = 1; b = 2; c = 3; }
我們把常用的變量寫到最上面,可以進行注釋,這樣更有利于維護我們的代碼,同時防止變量在定義之前使用的邏輯錯誤。
DOM操作的注意點腳本進行DOM的操作的代價是很昂貴的。它是富Web應用中最常見的性能瓶頸。瀏覽器中通常會把DOM 和 JavaScript(ECMAScript) 獨立實現。我們每一次用js去操作DOM都會產生性能消耗,所以我們盡可能小的去處理DOM,這也是現在MVVM和MVC框架流行的一部分原因。我們在處理DOM時盡可能這樣做。
1.最小化DOM訪問次數,盡可能在JavaScript端處理
var ul = document.getElementById("ul"); var a = ""; for(var i=0;i<10;i++){ a += "
"; } ul.innerHTML = a;
將要添加的標簽存儲在變量a中,一次性加入ul中,這樣只訪問一次dom,降低了性能消耗。
2.如果需要多次訪問某個DOM節點,請使用局部變量存儲它的引用
var doc = document; // 存儲document doc.getElementById("div");
3.小心處理HTML集合,因為它實時連系著底層文檔,把集合的長度緩存到一個變量中,并在迭代中使用它。如果需要經常操作集合,建議把它拷貝到一個數組中。
var divList = document.getElementsByTagName("div"); for(var i = 0,len = divList.length; i < len; i++){ }
這里我們將divList的長度去存儲在變量 len中,而不像下面這樣每次循環都要讀取一遍長度。
// 避免使用的例子 var divList = document.getElementsByTagName("div"); for(var i = 0; i < divList.length; i++){ }
4.如果可能的話,使用速度更快的API,比如querySelectorAll() 和 firstElementChild
5.要留意重繪和重排;批量修改樣式時,"離線"操作DOM樹,使用緩存、并減少訪問布局信息的次數
瀏覽器下載完頁面中的所有組件之后會解析并生成兩個內部數據結構
DOM樹: 表示頁面結構
渲染樹: 表示DOM節點如何顯示
當DOM的變化影響了元素的幾何屬性時(寬高)—— 比如改變框寬度或給段落增加文字,導致行數增加,瀏覽器需要重新計算元素的幾何屬性,同樣其他元素的幾何屬性和位置也會因此受到影響,瀏覽器會是渲染樹中受到影響的部分失效,并重新構造渲染樹。這一過程稱為 “重排(reflow)”。完成重排后,瀏覽器會重新繪制影響的部分到屏幕中,該過程稱為 “重繪”。
那么我們該怎么減少重排和重繪
樣式統一處理
我們在改變一個元素樣式時,可以統一處理
//這種寫法不推薦 var el = document.getElementById("div"); el.style.width = "100px"; el.style.height = "100px"; el.style.padding = "10px"; //這種寫法推薦 var el = document.getElementById("div"); el.style.cssText = "width:100px;height:100px;padding:5px;";
下邊的方法很明顯只進行了一次重排,而上邊的重排了三次。使用cssText時會覆蓋前邊的style樣式,我們可以這樣做
el.style.cssText += "width:100px;height:100px;padding:5px;";
另外我們還可以將改變的樣式寫在css樣式表中,通過修改class來改變其樣式。
var el = document.getElementById("div"); el.className = "active";
脫離文檔流修改DOM
脫離文檔修改DOM的步驟就是
使元素脫離文檔流
對其應用多重改變
把元素帶回文檔中
這里我有三種方法:
(1) 第一種:隱藏元素,應用修改,重新顯示
var el = document.getElementById("div"); el.style.display = "none"; el.style.width = "100px"; el.style.height = "100px"; el.style.padding = "10px"; el.style.display = "block";
(2) 第二種:使用文檔片段在當前DOM之外構建一個子樹,在把它拷貝回文檔
var el = document.getElementById("ul"); var fragment = document.createDocumentFragment(); for(var i = 0; i < 50000; i++){ fragment.appendChild(document.createElement("li")); } el.appenChild(fragment);
推薦使用這種方式。
(3) 第三種:將原始元素拷貝到一個脫離文檔的節點中,修改副本,完成后在提貨原始元素
var el = document.getElementById("div"); var cloneDiv = el.choleNode(true); cloneDiv.appendChild = li; el.parentNode.replaceChild(clone,el);
以上脫離文檔流修改DOM的方法推薦第二種方法。
減少渲染變化的排隊與刷新
由于每次重排都會產生計算消耗,大多數瀏覽器通過列隊化修改并批量執行來優化重排過程。而我們不知不覺中就使用了一些強制刷新隊列并要求計劃任務立刻執行的方法:
1. offsetTop、offsetLeft、offsetWidth、offsetHeight 2. scrollTop、scrollLeft、scrollWidth、scrollHeight 3. clientTop、clientLeft、clientWidht、clientHeight 4. getComputedStyle() // currentStyle IE中
我們在使用上面方法時要注意,瀏覽器為了返回最新值,會刷新隊列應用所用變更,我們應該減少他們的使用,如果使用他們我們最好緩存布局信息
例如我們將滾輪滾動到頁面頂部:
var scroll = document.body.scrollTop; // 這里直接緩存scrollTop var set = setInterval(function(){ scroll--; // 這里不使用window.scrollTop-- document.body.scrollTop = scroll; if(scroll < 0) { clearInterval(set); } },100)
6.動畫中使用絕對定位。
對于用展開/折疊的效果,我們使用絕對定位,將其脫離文檔流,會是重繪更少些。
7.使用事件委托來減少事件處理器的數量。
如果你還不知道事件委托事什么,請訪問:
http://blog.csdn.net/webxiaoma/article/details/53501616
這里我們討論的是循環和判斷,我們直接寫推薦的書寫方法
1.循環體
循環包括 for循環、while循環、do-while循環、for-in循環。
其中for-in循環的性能明顯比其他性能差些,另外ES6對于屬性循環有出了for-of循環,比起for-in循環性能要好一些。
我們前面也說了,循環時,我們最好存儲判斷的長度,另外遞減循環要比遞加循環速度相當要快。
2.判斷
判斷有:if 和 switch;
當我們做判斷時,最好是吧最有可能出現的放到前面,另外if-else-if很多的話,推薦使用switch去判斷,這樣更有利于減少性能的消耗。有時候我們選擇嵌套if也不使用很多if-else-if連用的方法如下:
// 推薦 if(){ if(){ if(){ } } } // 盡量少用 if(){ } else if(){ } else if(){ } else if(){ } else if(){ } else if(){ }對象和作用域
對象的注意點是:
1.盡量不擴展內置原型(如給Object.prototype添加自己的方法),除非你確定不會對你的團隊造成影響
2.訪問的作用域和對象越深,越消耗性能,我們 盡量減少,不過這并不是硬性的要求,我們盡量減少那些不必要的深入訪問。
其他注意點避免隱士類型轉換(有時候判斷需要考慮用全等號還是雙等號)
var a = 0; if(a === false){ //不執行 } if(a == false){ //執行了 }
2.盡量少的使用eval()
3.項目發布時的代碼壓縮,js文件整合,圖片整合等等優化。
4.整個團隊的代碼書寫風格,要確定。
結束文章基本就寫到這里,項目書寫的注意點不單單只有這些,其實對代碼的優化還有很多,還有你的經驗。不斷積累一定會寫成很優雅的代碼。
參考文獻:《高性能JavaScript》
文章版權歸作者所有,未經允許請勿轉載,若此文章存在違規行為,您可以聯系管理員刪除。
轉載請注明本文地址:http://specialneedsforspecialkids.com/yun/89328.html
摘要:不單單是因為引起的。用與要注意的地方這里要注意的是這二個函數的第一個參數都會把指向還有第一個參數可以為但不要這樣用因為這樣等于自己隱式使用了。 自動分號插入 Js不像其他語言強制要求;號結尾不然編譯不過,原因是JS有自動;號的插入。 var text=function(){} text() 這樣你不加;號也能運行其實在內部js是需要;號去幫助解析的 var text=function(...
摘要:解決方式是,當我們不使用它們的時候,手動切斷鏈接淘汰把和對象轉為了真正的對象,避免了使用這種垃圾收集策略,消除了以下常見的內存泄漏的主要原因。以上參考資料高程垃圾收集類內存泄漏及如何避免內存泄露及解決方案詳解類內存泄漏及如何避免 showImg(http://ww1.sinaimg.cn/large/005Y4rCogy1ft1ikzcqzqj30ka0et77a.jpg); 前言 起...
摘要:比特幣和以太幣屬于一類區塊鏈,我們將其歸類為公共無許可的區塊鏈技術。例如,在單個企業中部署時,或由受信任的權威機構運作,完全拜占庭容錯的共識可能被認為是不必要的,并且對性能和吞吐量造成過度的拖累。 介紹 一般而言,區塊鏈是一個不可變的交易分類賬,維護在一個分布式對等節點網絡中。這些節點通過應用已經由共識協議驗證的交易來維護分類帳的副本,該交易被分組為包括將每個塊綁定到前一個塊的散列的塊...
閱讀 2571·2021-11-22 09:34
閱讀 932·2021-11-19 11:34
閱讀 2801·2021-10-14 09:42
閱讀 1472·2021-09-22 15:27
閱讀 2385·2021-09-07 09:59
閱讀 1731·2021-08-27 13:13
閱讀 3432·2019-08-30 11:21
閱讀 771·2019-08-29 18:35