成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

如何提高web前端的性能優(yōu)化

如何提高web前端的性能優(yōu)化,相信很多沒有經(jīng)驗的人對此束手無策,為此本文總結(jié)了問題出現(xiàn)的原因和解決方法,通過這篇文章希望你能解決這個問題。

創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設、高性價比青陽網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式青陽網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設找我們,業(yè)務覆蓋青陽地區(qū)。費用合理售后完善,十載實體公司更值得信賴。

前端性能優(yōu)化是一個不斷追求的過程,前面的文章雖然講解了一些性能優(yōu)化,但是關于性能優(yōu)化的路還有很長,很多東西都沒有提及。
運算符

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

2、位運算。

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

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

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

常規(guī)優(yōu)化
1、switch語句。

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

例如:

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文章優(yōu)化中,提及了這一項。

代碼如下:

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(),接受字符串或者方法實例作為參數(shù)。直接傳遞方法對象作為參數(shù)來避免對字符串的二次解析。

傳遞方法

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

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

4、使用原始操作代替方法調(diào)用

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

原始操作

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

5、定時器

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

6、最小化語句數(shù)

例如:

多個變量聲明

/**不提倡**/
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++];

使用數(shù)組和對象字面量,避免使用構(gòu)造函數(shù)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
};

類型轉(zhuǎn)換

1、把數(shù)字轉(zhuǎn)換成字符串。

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

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

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

2、浮點數(shù)轉(zhuǎn)換成整型。

錯誤使用使用parseInt()。

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

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

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

循環(huán)
1、定義變量,避免每次獲取

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

2、避免在循環(huán)中使用try-catch。

try-catch-finally語句在catch語句被執(zhí)行的過程中會動態(tài)構(gòu)造變量插入到當前域中,對性能有一定影響。

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

循環(huán)外使用try-catch

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

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

作用域鏈和閉包優(yōu)化
1、作用域。

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

函數(shù)的調(diào)用
with語句
with會創(chuàng)建自已的作用域,因此會增加其中執(zhí)行代碼的作用域的長度。
全局作用域。

以下代碼為例:

var foo = function() {
  var local = {};
};
foo();
console.log(local); //=> undefined

var bar = function() {
  local = {};
};
bar();
console.log(local); //=> {}

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

local = {};
// 這里的定義等效于
global.local = {};

2、作用域鏈

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

function foo() {
  var val = 'hello';
  function bar() {
    function baz() {
      global.val = 'world;'
    };
    baz();
    console.log(val); //=> hello
  };
  bar();
};
foo();

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

3、減少作用域鏈上的查找次數(shù)

/**效率低**/
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");
}
/**上面代碼中,第二種情況是先把全局對象的變量放到函數(shù)里面先保存下來,然后直接訪問這個變量,而第一種情況是每次都遍歷作用域鏈,直到全局環(huán)境,我們看到第二種情況實際上只遍歷了一次,而第一種情況卻是每次都遍歷了,而且這種差別在多級作用域鏈和多個全局變量的情況下還會表現(xiàn)的非常明顯。在作用域鏈查找的次數(shù)是`O(n)`。通過創(chuàng)建一個指向`document`的局部變量,就可以通過限制一次全局查找來改進這個函數(shù)的性能。**/

4、閉包

JAVASCRIPT中的標識符查找遵循從內(nèi)到外的原則。

function foo() {
  var local = 'Hello';
  return function() {
    return local;
  };
}
var bar = foo();
console.log(bar()); //=> Hello

/**這里所展示的讓外層作用域訪問內(nèi)層作用域的技術(shù)便是閉包(Closure)。得益于高階函數(shù)的應用,使foo()函數(shù)的作用域得到`延伸`。foo()函數(shù)返回了一個匿名函數(shù),該函數(shù)存在于foo()函數(shù)的作用域內(nèi),所以可以訪問到foo()函數(shù)作用域內(nèi)的local變量,并保存其引用。而因這個函數(shù)直接返回了local變量,所以在外層作用域中便可直接執(zhí)行bar()函數(shù)以獲得local變量。**/

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

良好的閉包管理。

循環(huán)事件綁定、私有屬性、含參回調(diào)等一定要使用閉包時,并謹慎對待其中的細節(jié)。

循環(huán)綁定事件,我們假設一個場景:有六個按鈕,分別對應六種事件,當用戶點擊按鈕時,在指定的地方輸出相應的事件。

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

避開閉包陷阱

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

閉包的性能不如使用內(nèi)部方法,更不如重用外部方法。

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

善用函數(shù)

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

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

有的甚至更高級一點:

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

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

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

善用回調(diào)函數(shù)
在制作網(wǎng)頁過程中,用的比較多的地方,我們通常封裝成函數(shù)。在封裝函數(shù)的時候,善用運用回調(diào)函數(shù)。

例子如下:

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

}

我們在調(diào)用的時候可以如下:

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

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

尾部插入元素

我們有2個數(shù)組

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);

發(fā)現(xiàn):

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

向數(shù)組中間添加元素

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

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

看完上述內(nèi)容,你們掌握如何提高web前端的性能優(yōu)化的方法了嗎?如果還想學到更多技能或想了解更多相關內(nèi)容,歡迎關注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝各位的閱讀!

當前題目:如何提高web前端的性能優(yōu)化
當前鏈接:http://jinyejixie.com/article18/possdp.html

成都網(wǎng)站建設公司_創(chuàng)新互聯(lián),為您提供做網(wǎng)站App設計、微信公眾號、網(wǎng)站制作、云服務器、電子商務

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

成都做網(wǎng)站
南投县| 确山县| 东光县| 江永县| 崇信县| 偏关县| 泗水县| 浦县| 新昌县| 蚌埠市| 东乡县| 吉林市| 新昌县| 安国市| 壤塘县| 方城县| 修水县| 镇坪县| 文登市| 台州市| 永德县| 望奎县| 拉孜县| 新巴尔虎左旗| 邵东县| 横峰县| 叙永县| 藁城市| 调兵山市| 巴林左旗| 易门县| 永善县| 资阳市| 福泉市| 南开区| 深泽县| 介休市| 大同县| 精河县| 邻水| 桐柏县|