在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ 淺談 JavaScript 的執(zhí)行效率
淺談 JavaScript 之事件綁定
淺談 javascript 中字符串 String 與數(shù)組 Array
淺談 javascript 中基本包裝類型
淺談 JavaScript Math 和 Number 對(duì)象
淺談 Javascript 的靜態(tài)屬性和原型屬性
淺談 JavaScript 中定義變量時(shí)有無(wú) var 聲明的區(qū)別
淺談 JavaScript Array 對(duì)象
淺談 JavaScript 函數(shù)參數(shù)的可修改性問(wèn)題
淺談 javascript 中的 instanceof 和 typeof
淺談 JavaScript 中 Date (日期對(duì)象),Math 對(duì)象
淺談 Javascript 執(zhí)行順序
淺談 javascript 函數(shù)屬性和方法
淺談 JavaScript 中面向?qū)ο蠹夹g(shù)的模擬
淺談 javascript 的原型繼承
淺談 javascript 事件取消和阻止冒泡
根據(jù)一段代碼淺談 Javascript 閉包
淺談 Javascript 面向?qū)ο缶幊?/span>
淺談 javascript 六種數(shù)據(jù)類型以及特殊注意點(diǎn)
淺談 Javascript 變量作用域問(wèn)題
淺談 javascript 函數(shù)內(nèi)部屬性
淺談 javascript 中自定義模版
淺談 JavaScript 字符集
淺談 javascript 面向?qū)ο缶幊?/span>
淺談 JavaScript 框架分類
淺談 JavaScript 中的 Math.atan() 方法的使用
淺談 Javascript 數(shù)組與字典
淺談 JavaScript 數(shù)據(jù)類型及轉(zhuǎn)換
淺談 javascript 的調(diào)試
淺談 Javascript 嵌套函數(shù)及閉包
淺談 javascript 回調(diào)函數(shù)
淺談 JavaScript Date 日期和時(shí)間對(duì)象
淺談 Javascript 中的 Function 與 Object
淺談 JavaScript 數(shù)據(jù)類型
淺談 javascript 中 this 在事件中的應(yīng)用
淺談 javascript 中的閉包
淺談 javascript 函數(shù)劫持
淺談 Javascript 中深復(fù)制
淺談 JavaScript 函數(shù)節(jié)流
淺談 JavaScript 中的 String 對(duì)象常用方法
淺談 JavaScript 事件的屬性列表
淺談 JavaScript 函數(shù)與棧
淺談 JavaScript 的事件
淺談 javascript 中的作用域
淺談 JavaScript 的執(zhí)行效率
淺談 Javascript 事件模擬
淺談 JavaScript function 函數(shù)種類
淺談 javascript 歸并方法
淺談 javascript 迭代方法
淺談 JavaScript 編程語(yǔ)言的編碼規(guī)范
淺談 JavaScript 實(shí)現(xiàn)面向?qū)ο笾械念?/span>
淺談 Javascript 鼠標(biāo)和滾輪事件
淺談 Javascript Base64 加密解密
淺談 Javascript 中勻速運(yùn)動(dòng)的停止條件
淺談 javascript 實(shí)現(xiàn)八大排序
淺談 javascript 的分號(hào)的使用
淺談 javascript 中 createElement 事件
淺談 javascript 的數(shù)據(jù)類型檢測(cè)
淺談 javascript 對(duì)象模型和 function 對(duì)象
淺談 Javascript 如何實(shí)現(xiàn)勻速運(yùn)動(dòng)
淺談 JavaScript 字符串與數(shù)組
淺談 javascript 面向?qū)ο蟪绦蛟O(shè)計(jì)
淺談 Javascript 事件處理程序的幾種方式

淺談 JavaScript 的執(zhí)行效率

Javascript 是一門非常靈活的語(yǔ)言,我們可以隨心所欲的書(shū)寫各種風(fēng)格的代碼,不同風(fēng)格的代碼也必然也會(huì)導(dǎo)致執(zhí)行效率的差異,開(kāi)發(fā)過(guò)程中零零散散地接觸到許多提高代碼性能的方法,整理一下平時(shí)比較常見(jiàn)并且容易規(guī)避的問(wèn)題。

Javascript 自身執(zhí)行效率

Javascript 中的作用域鏈、閉包、原型繼承、eval 等特性,在提供各種神奇功能的同時(shí)也帶來(lái)了各種效率問(wèn)題,用之不慎就會(huì)導(dǎo)致執(zhí)行效率低下。

全局導(dǎo)入

我們?cè)诰幋a過(guò)程中多多少少會(huì)使用到一些全局變量(window,document,自定義全局變量等等),了解 javascript 作用域鏈的人都知道,在局部作用域中訪問(wèn)全局變量需要一層一層遍歷整個(gè)作用域鏈直至頂級(jí)作用域,而局部變量的訪問(wèn)效率則會(huì)更快更高,因此在局部作用域中高頻率使用一些全局對(duì)象時(shí)可以將其導(dǎo)入到局部作用域中,例如:

//1、作為參數(shù)傳入模塊
  (function(window,$){
      var xxx = window.xxx;
      $("#xxx1").xxx();
      $("#xxx2").xxx();
  })(window,jQuery);

  //2、暫存到局部變量
  function(){
     var doc = document;
     var global = window.global;
 }

eval 以及類 eval 問(wèn)題

我們都知道 eval 可以將一段字符串當(dāng)做 js 代碼來(lái)執(zhí)行處理,據(jù)說(shuō)使用 eval 執(zhí)行的代碼比不使用 eval 的代碼慢 100 倍以上(具體效率我沒(méi)有測(cè)試,有興趣同學(xué)可以測(cè)試一下)。

JavaScript 代碼在執(zhí)行前會(huì)進(jìn)行類似“預(yù)編譯”的操作:首先會(huì)創(chuàng)建一個(gè)當(dāng)前執(zhí)行環(huán)境下的活動(dòng)對(duì)象,并將那些用 var 申明的變量設(shè)置為活動(dòng)對(duì)象的屬性,但是此時(shí)這些變量的賦值都是 undefined,并將那些以 function 定義的函數(shù)也添加為活動(dòng)對(duì)象的屬性,而且它們的值正是函數(shù)的定義。但是,如果你使用了“eval”,則“eval”中的代碼(實(shí)際上為字符串)無(wú)法預(yù)先識(shí)別其上下文,無(wú)法被提前解析和優(yōu)化,即無(wú)法進(jìn)行預(yù)編譯的操作。所以,其性能也會(huì)大幅度降低。

其實(shí)現(xiàn)在大家一般都很少會(huì)用 eval 了,這里我想說(shuō)的是兩個(gè)類 eval 的場(chǎng)景(new Function{},setTimeout,setInterver)

setTimtout("alert(1)",1000);

setInterver("alert(1)",1000);

(new Function("alert(1)"))();

上述幾種類型代碼執(zhí)行效率都會(huì)比較低,因此建議直接傳入匿名方法、或者方法的引用給 setTimeout 方法。

閉包結(jié)束后釋放掉不再被引用的變量

var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //****其它變量
    //***一些運(yùn)算
    var res = function(){
        alert(a.name);
    }
    return res;
})()

上述代碼中變量 f 的返回值是由一個(gè)立即執(zhí)行函數(shù)構(gòu)成的閉包中返回的方法 res,該變量保留了對(duì)于這個(gè)閉包中所有變量(a,b,c 等)的引用,因此這兩個(gè)變量會(huì)一直駐留在內(nèi)存空間中,尤其是對(duì)于 dom 元素的引用對(duì)內(nèi)存的消耗會(huì)很大,而我們?cè)?res 中只使用到了 a 變量的值,因此,在閉包返回前我們可以將其它變量釋放。

var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //****其它變量
    //***一些運(yùn)算
    //閉包返回前釋放掉不再使用的變量
    b = c = null;
    var res = function(){
        alert(a.name);
        }
    return res;
})()

Js 操作 dom 的效率

在 web 開(kāi)發(fā)過(guò)程中,前端執(zhí)行效率的瓶頸往往都是在 dom 操作上面,dom 操作是一件很耗性能的事情,如何才能在 dom 操作過(guò)程中盡量節(jié)約性能呢?

減少 reflow

什么是 reflow?

當(dāng) DOM 元素的屬性發(fā)生變化 (如 color) 時(shí),瀏覽器會(huì)通知 render 重新描繪相應(yīng)的元素,此過(guò)程稱為 repaint。

如果該次變化涉及元素布局(如 width),瀏覽器則拋棄原有屬性,重新計(jì)算并把結(jié)果傳遞給 render 以重新描繪頁(yè)面元素,此過(guò)程稱為 reflow。

減少 reflow 的方法

先將元素從 document 中刪除,完成修改后再把元素放回原來(lái)的位置(當(dāng)對(duì)某元素及其子元素進(jìn)行大量 reflow 操作時(shí),1,2 兩種方法效果才會(huì)比較明顯)
將元素的 display 設(shè)置為”none”,完成修改后再把 display 修改為原來(lái)的值
修改多個(gè)樣式屬性時(shí)定義 class 類代替多次修改 style 屬性(for certain 同學(xué)推薦)
大量添加元素到頁(yè)面時(shí)使用 documentFragment

例如:

for(var i=0;i<100:i++){
    var child = docuemnt.createElement("li");
    child.innerHtml = "child";
    document.getElementById("parent").appendChild(child);
}

上述代碼會(huì)多次操作 dom,效率比較低,可以改為下面的形式 創(chuàng)建 documentFragment,將所有元素加入到 docuemntFragment 不會(huì)改變 dom 結(jié)構(gòu),最后將其添加到頁(yè)面,只進(jìn)行了一次 reflow。

var frag = document.createDocumentFragment();
for(var i=0;i<100:i++){
        var child = docuemnt.createElement("li");
        child.innerHtml = "child";
    frag.appendChild(child);
}
document.getElementById("parent").appendChild(frag);

暫存 dom 狀態(tài)信息

當(dāng)代碼中需要多次訪問(wèn)元素的狀態(tài)信息,在狀態(tài)不變的情況下我們可以將其暫存到變量中,這樣可以避免多次訪問(wèn) dom 帶來(lái)內(nèi)存的開(kāi)銷,典型的例子就是:

var lis = document.getElementByTagName("li");
for(var i=1;i<lis.length;i++){
    //***
}

上述方式會(huì)在每一次循環(huán)都去訪問(wèn)dom元素,我們可以簡(jiǎn)單將代碼優(yōu)化如下:

var lis = document.getElementByTagName("li");
for(var i=1,j=lis.length ;i<j;i++){
    //***
}

縮小選擇器的查找范圍

查找 dom 元素時(shí)盡量避免大面積遍歷頁(yè)面元素,盡量使用精準(zhǔn)選擇器,或者指定上下文以縮小查找范圍,以 jquery 為例:

少用模糊匹配的選擇器:例如 $("[name*='_fix']"),多用諸如 id 以及逐步縮小范圍的復(fù)合選擇器 $("li.active") 等

指定上下文:例如 $("#parent .class"),$(".class",$el) 等

使用事件委托

使用場(chǎng)景:一個(gè)有大量記錄的列表,每條記錄都需要綁定點(diǎn)擊事件,在鼠標(biāo)點(diǎn)擊后實(shí)現(xiàn)某些功能,我們通常的做法是給每條記錄都綁定監(jiān)聽(tīng)事件,這種做法會(huì)導(dǎo)致頁(yè)面會(huì)有大量的事件監(jiān)聽(tīng)器,效率比較低下。

基本原理:我們都知道 dom 規(guī)范中事件是會(huì)冒泡的,也就是說(shuō)在不主動(dòng)阻止事件冒泡的情況下任何一個(gè)元素的事件都會(huì)按照 dom 樹(shù)的結(jié)構(gòu)逐級(jí)冒泡至頂端。而 event 對(duì)象中也提供了 event.target(IE 下是 srcElement)指向事件源,因此我們即使在父級(jí)元素上監(jiān)聽(tīng)該事件也可以找到觸發(fā)該事件的最原始的元素,這就是委托的基本原理。廢話不多說(shuō),上示例:

$("ul li").bind("click",function(){
    alert($(this).attr("data"));
})

上述寫法其實(shí)是給所有的 li 元素都綁定了 click 事件來(lái)監(jiān)聽(tīng)鼠標(biāo)點(diǎn)擊每一個(gè)元素的事件,這樣頁(yè)面上會(huì)有大量的事件監(jiān)聽(tīng)器。

根據(jù)上面介紹的監(jiān)聽(tīng)事件的原理我們來(lái)改寫一下:

$("ul").bind("click",function(e){
    if(e.target.nodeName.toLowerCase() ==="li"){
        alert($(e.target).attr("data"));
    }
})

這樣一來(lái),我們就可以只添加一個(gè)事件監(jiān)聽(tīng)器去捕獲所有 li 上觸發(fā)的事件,并做出相應(yīng)的操作。

當(dāng)然,我們不必每次都做事件源的判斷工作,可以將其抽象一下交給工具類來(lái)完成。jquery 中的 delegate()方法就實(shí)現(xiàn)了該功能

語(yǔ)法是這樣的 $(selector).delegate(childSelector,event,data,function),例如:

$("div").delegate("button","click",function(){
  $("p").slideToggle();
});

參數(shù)說(shuō)明(引自w3school)

參數(shù) 描述
childSelector 必需。規(guī)定要附加事件處理程序的一個(gè)或多個(gè)子元素。
event 必需。規(guī)定附加到元素的一個(gè)或多個(gè)事件。由空格分隔多個(gè)事件值。必須是有效的事件。
data 可選。規(guī)定傳遞到函數(shù)的額外數(shù)據(jù)。
function 必需。規(guī)定當(dāng)事件發(fā)生時(shí)運(yùn)行的函數(shù)。

Tips: 事件委托還有一個(gè)好處就是,即使在事件綁定之后動(dòng)態(tài)添加的元素上觸發(fā)的事件同樣可以監(jiān)聽(tīng)到哦,這樣就不用在每次動(dòng)態(tài)加入元素到頁(yè)面后都為其綁定事件了。