亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 網站 > 建站經驗 > 正文

前端性能優化補充篇

2024-04-25 20:46:59
字體:
來源:轉載
供稿:網友

前言

看了一下之前發布的文章,關于前端性能優化的,有網站前端性能優化之javascript和css及jquery的 jquery編程的標準寫法和最佳實踐 。前端性能優化是一個不斷追求的過程,前面的文章雖然講解了一些性能優化,但是關于性能優化的路還有很長,很多東西都沒有提及。今天,我在前面的基礎之上,再來簡單總結一些常用的性能優化方式。

運算符

1、使用運算符時,盡量使用+=,-=、*=、/=等運算符號,而不是直接進行賦值運算。

2、位運算。

當進行數學運算時位運算較快,位運算操作要比任何布爾運算或算數運算快,如取模,邏輯與和邏輯或也可以考慮用位運算來替換。

有同學問,常見的js位運算符有哪些?常見的位運算符有“~,&,|,^,.<<,>>,>>>”等等。

關于位運算的應用,我前面也有文章提及,js運算符單豎杠“|”的用法和作用是什么?以及javascript實用技巧,js小知識大家可以去看看。

常規優化
1、switch語句。

若有一系列復雜的if-else語句,可以轉換成單個switch語句則可以得到更快的代碼,還可以通過將case語句按照最可能的到最不可能的順序進行組織,來進一步優化。

例如:

function getCategory(age) {    var category = "";    switch (true) {        case isNaN(age):            category = "not an age";            break;        case (age >= 50):            category = "Old";            break;        case (age <= 20):            category = "Baby";            break;        default:            category = "Young";            break;    };    return category;}getCategory(5);  //Baby

這樣的稍微復雜一些的,我們盡量就不用if/else了,當然,簡單的判斷,還是推薦if/else。

2、減少頁面的重繪

我的jquery文章優化中,提及了這一項。

代碼如下:

var str = "<div>這是一個測試字符串</div>";/**效率低**/var obj = document.getElementsByTagName("body");for(var i = 0; i < 100; i++){    obj.innerHTML += str + i;}/**效率高**/var obj = document.getElementsByTagName("body");var arr = [];for(var i = 0; i < 100; i++){    arr[i] = str + i;}obj.innerHTML = arr.join("");

3、傳遞方法取代方法字符串

一些方法例如setTimeout()、setInterval(),接受字符串或者方法實例作為參數。直接傳遞方法對象作為參數來避免對字符串的二次解析。

傳遞方法

setTimeout(test, 1);//good
傳遞方法字符串

setTimeout('test()', 1);//不能說bad,只能說not good

4、使用原始操作代替方法調用

方法調用一般封裝了原始操作,在性能要求高的邏輯中,可以使用原始操作代替方法調用來提高性能。

原始操作

var min = a<b?a:b; //good
方法實例
var min = Math.min(a, b);//not good

5、定時器

如果針對的是不斷運行的代碼,不應該使用setTimeout,而應該是用setInterval。setTimeout每次要重新設置一個定時器。

6、最小化語句數

例如:

多個變量聲明

/**不提倡**/var i = 1;var j = "hello";var arr = [1,2,3];var now = new Date();/**提倡**/var i = 1,    j = "hello",    arr = [1,2,3],    now = new Date();

插入迭代值

/**不提倡**/var name = values[i];i++;/**提倡**/var name = values[i++];

使用數組和對象字面量,避免使用構造函數Array(),Object()

/**不提倡**/var a = new Array();a[0] = 1;a[1] = "hello";a[2] = 45;var o = new Obejct();o.name = "bill";o.age = 13;/**提倡**/var a = [1, "hello", 45];var o = {    name : "bill",    age : 13};

類型轉換

1、把數字轉換成字符串。

應用""+1,效率是最高。

性能上來說:""+字符串>String()>.toString()>new String()。

String()屬于內部函數,所以速度很快。.toString()要查詢原型中的函數,所以速度略慢。new String()最慢。

2、浮點數轉換成整型。

錯誤使用使用parseInt()。

parseInt()是用于將字符串轉換成數字,而不是浮點數和整型之間的轉換。

應該使用Math.floor()或者Math.round()。

Math是內部對象,所以Math.floor()其實并沒有多少查詢方法和調用的時間,速度是最快的。

循環
1、定義變量,避免每次獲取

/**效率低**/   var divs = document.getElementsByTagName("div");    for(var i = 0; i < divs.length; i++){       ...  }    /**效率高,適用于獲取DOM集合,如果純數組則兩種情況區別不大**/  var divs = document.getElementsByTagName("div");   for(var i = 0, len = divs.length; i < len; i++){       ... }

2、避免在循環中使用try-catch。

try-catch-finally語句在catch語句被執行的過程中會動態構造變量插入到當前域中,對性能有一定影響。

如果需要異常處理機制,可以將其放在循環外層使用。

循環外使用try-catch

try {  for ( var i = 0; i < 200; i++) {}} catch (e){}

3、避免遍歷大量元素,盡量縮小遍歷范圍。

作用域鏈和閉包優化
1、作用域。

作用域(scope)是JAVASCRIPT編程中一個重要的運行機制,在JAVASCRIPT同步和異步編程以及JAVASCRIPT內存管理中起著至關重要的作用。 在JAVASCRIPT中,能形成作用域的有如下幾點。

函數的調用with語句with會創建自已的作用域,因此會增加其中執行代碼的作用域的長度。全局作用域。

以下代碼為例:

var foo = function() {  var local = {};};foo();console.log(local); //=> undefinedvar bar = function() {  local = {};};bar();console.log(local); //=> {}/**這里我們定義了foo()函數和bar()函數,他們的意圖都是為了定義一個名為local的變量。在foo()函數中,我們使用var語句來聲明定義了一個local變量,而因為函數體內部會形成一個作用域,所以這個變量便被定義到該作用域中。而且foo()函數體內并沒有做任何作用域延伸的處理,所以在該函數執行完畢后,這個local變量也隨之被銷毀。而在外層作用域中則無法訪問到該變量。而在bar()函數內,local變量并沒有使用var語句進行聲明,取而代之的是直接把local作為全局變量來定義。故外層作用域可以訪問到這個變量。**/local = {};// 這里的定義等效于global.local = {};

2、作用域鏈

在JAVASCRIPT編程中,會遇到多層函數嵌套的場景,這就是典型的作用域鏈的表示。

function foo() {  var val = 'hello';  function bar() {    function baz() {      global.val = 'world;'    };    baz();    console.log(val); //=> hello  };  bar();};foo();/**在`JAVASCRIPT`中,變量標識符的查找是從當前作用域開始向外查找,直到全局作用域為止。所以`JAVASCRIPT`代碼中對變量的訪問只能向外進行,而不能逆而行之。baz()函數的執行在全局作用域中定義了一個全局變量val。而在bar()函數中,對val這一標識符進行訪問時,按照從內到外的查找原則:在bar函數的作用域中沒有找到,便到上一層,即foo()函數的作用域中查找。然而,使大家產生疑惑的關鍵就在這里:本次標識符訪問在foo()函數的作用域中找到了符合的變量,便不會繼續向外查找,故在baz()函數中定義的全局變量val并沒有在本次變量訪問中產生影響。**/

3、減少作用域鏈上的查找次數

/**效率低**/for(var i = 0; i < 10000; i++){    var but1 = document.getElementById("but1");}/**效率高**//**避免全局查找**/var doc = document;for(var i = 0; i < 10000; i++){    var but1 = doc.getElementById("but1");}/**上面代碼中,第二種情況是先把全局對象的變量放到函數里面先保存下來,然后直接訪問這個變量,而第一種情況是每次都遍歷作用域鏈,直到全局環境,我們看到第二種情況實際上只遍歷了一次,而第一種情況卻是每次都遍歷了,而且這種差別在多級作用域鏈和多個全局變量的情況下還會表現的非常明顯。在作用域鏈查找的次數是`O(n)`。通過創建一個指向`document`的局部變量,就可以通過限制一次全局查找來改進這個函數的性能。**/

4、閉包

JAVASCRIPT中的標識符查找遵循從內到外的原則。

function foo() {  var local = 'Hello';  return function() {    return local;  };}var bar = foo();console.log(bar()); //=> Hello/**這里所展示的讓外層作用域訪問內層作用域的技術便是閉包(Closure)。得益于高階函數的應用,使foo()函數的作用域得到`延伸`。foo()函數返回了一個匿名函數,該函數存在于foo()函數的作用域內,所以可以訪問到foo()函數作用域內的local變量,并保存其引用。而因這個函數直接返回了local變量,所以在外層作用域中便可直接執行bar()函數以獲得local變量。**/

閉包是JAVASCRIPT的高級特性,因為把帶有??內部變量引用的函數帶出了函數外部,所以該作用域內的變量在函數執行完畢后的并不一定會被銷毀,直到內部變量的引用被全部解除。所以閉包的應用很容易造成內存無法釋放的情況。

良好的閉包管理。

循環事件綁定、私有屬性、含參回調等一定要使用閉包時,并謹慎對待其中的細節。

循環綁定事件,我們假設一個場景:有六個按鈕,分別對應六種事件,當用戶點擊按鈕時,在指定的地方輸出相應的事件。var btns = document.querySelectorAll('.btn'); // 6 elementsvar output = document.querySelector('#output');var events = [1, 2, 3, 4, 5, 6];// Case 1for (var i = 0; i < btns.length; i++) {  btns[i].onclick = function(evt) {    output.innerText += 'Clicked ' + events[i];  };}/**這里第一個解決方案顯然是典型的循環綁定事件錯誤,這里不細說,詳細可以參照我給一個網友的回答;而第二和第三個方案的區別就在于閉包傳入的參數。**/// Case 2for (var i = 0; i < btns.length; i++) {  btns[i].onclick = (function(index) {    return function(evt) {      output.innerText += 'Clicked ' + events[index];    };  })(i);}/**第二個方案傳入的參數是當前循環下標,而后者是直接傳入相應的事件對象。事實上,后者更適合在大量數據應用的時候,因為在JavaScript的函數式編程中,函數調用時傳入的參數是基本類型對象,那么在函數體內得到的形參會是一個復制值,這樣這個值就被當作一個局部變量定義在函數體的作用域內,在完成事件綁定之后就可以對events變量進行手工解除引用,以減輕外層作用域中的內存占用了。而且當某個元素被刪除時,相應的事件監聽函數、事件對象、閉包函數也隨之被銷毀回收。**/// Case 3for (var i = 0; i < btns.length; i++) {  btns[i].onclick = (function(event) {    return function(evt) {      output.innerText += 'Clicked ' + event;    };  })(events[i]);}

避開閉包陷阱

閉包是個強大的工具,但同時也是性能問題的主要誘因之一。不合理的使用閉包會導致內存泄漏。

閉包的性能不如使用內部方法,更不如重用外部方法。

由于IE 9瀏覽器的DOM節點作為COM對象來實現,COM的內存管理是通過引用計數的方式,引用計數有個難題就是循環引用,一旦DOM引用了閉包(例如event handler),閉包的上層元素又引用了這個DOM,就會造成循環引用從而導致內存泄漏。

善用函數

使用一個匿名函數在代碼的最外層進行包裹。

;(function() { // 主業務代碼 })();

有的甚至更高級一點:

;(function(win, doc, $, undefined) {  // 主業務代碼})(window, document, jQuery);

甚至連如RequireJS, SeaJS, OzJS 等前端模塊化加載解決方案,都是采用類似的形式:

/**RequireJS**/define(['jquery'], function($) {  // 主業務代碼});/**SeaJS**/define('m??odule', ['dep', 'underscore'], function($, _) {  // 主業務代碼});

善用回調函數
在制作網頁過程中,用的比較多的地方,我們通常封裝成函數。在封裝函數的時候,善用運用回調函數。

例子如下:

function getData(callBack){    $.ajax({        url:"",        data:{},        dataType:"json",        type:"get",        success:function(data){            callBack(null,data)        }    })}

我們在調用的時候可以如下:

getData(function(error,data){ console.log(data)})

數組中插入元素最快的方法
向一個數組中插入元素是平時很常見的一件事情。你可以使用push在數組尾部插入元素,可以用unshift在數組頭部插入元素,也可以用splice在數組中間插入元素。 但是這些已知的方法,并不意味著沒有更加高效的方法。

尾部插入元素

我們有2個數組

var arr = [1,2,3,4,5];var arr2 = [];

測試如下:

 arr[arr.length] = 6; // 最快arr.push(6); // 慢34.66%arr2 = arr.concat([6]); // 慢85.79%

前面插入元素

var arr = [1,2,3,4,5];arr.unshift(0); [0].concat(arr);

發現:

[0].concat(arr); // 快arr.unshift(0); // 慢64.70%

向數組中間添加元素

使用splice可以簡單的向數組中間添加元素,這也是最高效的方法。

var items = ['one', 'two', 'three', 'four'];items.splice(items.length / 2, 0, 'hello');

 


注:相關教程知識閱讀請移步到建站經驗頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
68精品久久久久久欧美| 人九九综合九九宗合| 91高潮在线观看| 欧美成人在线免费| 日韩大片免费观看视频播放| 日韩女优在线播放| 欧美成人黑人xx视频免费观看| 久久天天躁日日躁| 久久琪琪电影院| 成人在线免费观看视视频| 日韩欧美精品网址| 97视频免费看| 亚洲国产成人爱av在线播放| 欧美亚洲国产成人精品| 日韩精品极品在线观看| 久久99热精品| 中文字幕日本精品| 久久久久免费视频| 精品国产一区久久久| 国产精品久久久久久久久影视| 韩曰欧美视频免费观看| 91成人在线播放| 欧美猛少妇色xxxxx| 欧美大片网站在线观看| 中文字幕精品www乱入免费视频| 日韩欧美在线观看| 黑人精品xxx一区一二区| 欧美激情视频播放| 国产欧美在线看| 色综合91久久精品中文字幕| 欧美—级高清免费播放| 奇米成人av国产一区二区三区| 国产精品成熟老女人| 久久久久久久久久久成人| 欧美日韩国产中文字幕| 亚洲激情自拍图| 97精品国产97久久久久久| 国产成人精品久久亚洲高清不卡| 久久久亚洲国产天美传媒修理工| 国产精品电影久久久久电影网| www.99久久热国产日韩欧美.com| 欧美国产日韩在线| 伊人伊人伊人久久| 国产精品尤物福利片在线观看| 97视频色精品| 亚洲自拍av在线| 欧美日韩激情视频8区| 欧美黑人一级爽快片淫片高清| 国产精品女视频| 在线视频亚洲欧美| 久久精品国产69国产精品亚洲| 97香蕉超级碰碰久久免费的优势| 日韩av高清不卡| 精品毛片三在线观看| 中文字幕无线精品亚洲乱码一区| 国产一区二区三区中文| 色天天综合狠狠色| 国产精品 欧美在线| 91chinesevideo永久地址| 欧美精品福利视频| 国产精品主播视频| 精品一区电影国产| 亚洲欧美999| 中文字幕精品在线视频| 青青久久aⅴ北条麻妃| 性色av一区二区三区在线观看| 欧美精品videosex性欧美| 成人性生交大片免费看小说| 成人性生交xxxxx网站| 欧美成人午夜影院| 欧美日韩亚洲视频| 久久久久久久久久久久av| 亚洲人永久免费| 国产精品久久一区| 日韩精品在线观看一区二区| 亚洲精品色婷婷福利天堂| 国产成人精品免高潮费视频| 亚洲欧美精品一区| 午夜精品一区二区三区在线视频| 亚洲成人久久久久| 欧美在线免费看| 久久人人看视频| 日韩中文字幕免费视频| 57pao成人永久免费视频| 亚洲欧美日韩天堂一区二区| 久久精品成人欧美大片古装| 亚洲国产一区自拍| 中文字幕国产精品| 在线看片第一页欧美| 亚洲色图美腿丝袜| 国产婷婷97碰碰久久人人蜜臀| 日韩在线资源网| 亚洲丝袜av一区| 欧美性猛交xxx| 亚洲在线www| 国产69精品久久久久99| 91久久国产精品| 国产精品免费久久久久影院| 亚州欧美日韩中文视频| 亚洲永久在线观看| 国产精品一区二区久久久| 精品视频在线播放色网色视频| 国产精品稀缺呦系列在线| 欧美在线视频一区| 亚洲精选在线观看| 亚洲欧美国产一区二区三区| 97国产精品久久| 韩曰欧美视频免费观看| 精品亚洲一区二区三区在线播放| 国产一区欧美二区三区| 97香蕉久久超级碰碰高清版| 在线播放国产一区中文字幕剧情欧美| 97视频在线观看成人| 91久久在线视频| 国产欧美最新羞羞视频在线观看| 久久97精品久久久久久久不卡| 日韩乱码在线视频| 欧美黄网免费在线观看| 日韩中文字幕免费| 亚洲毛片在线看| 欧美国产日韩一区| 成人黄色免费片| 日韩电视剧在线观看免费网站| 亚洲丝袜一区在线| 日韩免费看的电影电视剧大全| 亚洲黄色av女优在线观看| 欧美极品少妇与黑人| 日韩中文字幕免费| 国产91精品久| 91九色单男在线观看| 国产福利精品视频| 亚洲欧美国产精品va在线观看| 欧美中文在线观看| 精品国产一区二区三区久久狼5月| 青青久久av北条麻妃海外网| 成人免费在线视频网站| 久久亚洲一区二区三区四区五区高| 日韩av色在线| 亚洲美女av网站| 性欧美激情精品| 亚洲一区二区国产| 最近的2019中文字幕免费一页| 成人免费午夜电影| 中文日韩电影网站| 久久久久成人网| 国产精品欧美日韩一区二区| 欧美专区在线观看| 亚洲第一中文字幕在线观看| 亚洲一区二区久久久| 国产成人福利网站| 欧美劲爆第一页| 亚洲欧美国产一区二区三区| 久久久中精品2020中文| 色噜噜久久综合伊人一本| 欧美精品在线网站| 中国china体内裑精亚洲片| 国产在线久久久| 日韩小视频在线| 亚洲色图日韩av| 亚洲国产成人爱av在线播放| 97精品视频在线播放| 美女啪啪无遮挡免费久久网站| 亚洲福利视频在线| 久久视频国产精品免费视频在线|