目錄
1、全域導入
2、eval以及類別eval問題
3、閉包結束後釋放掉不再被引用的變數
1、減少reflow
什麼是reflow?
減少reflow的方法
2、暂存dom状态信息
3、缩小选择器的查找范围
4、使用事件委托
首頁 web前端 js教程 簡單介紹JavaScript的執行效率

簡單介紹JavaScript的執行效率

Mar 15, 2017 pm 05:25 PM

Javascript是一門非常靈活的語言,我們可以隨心所欲的書寫各種風格的程式碼,不同風格的程式碼也必然也會導致執行效率的差異,開發過程中零零散散地接觸到許多提升程式碼效能的方法,整理一下平時比較常見且容易規避的問題

Javascript本身執行效率

Javascript中的作用域鏈、閉包、原型繼承、eval等特性,在提供各種神奇功能的同時也帶來了各種效率問題,用之不慎就會導致執行效率低下。

1、全域導入

我們在編碼過程中多多少少會使用到一些全域變數(window,document,自訂全域變數等等),了解javascript作用域鏈的人都知道,在局部作用域中存取全域變數需要一層一層遍歷整個作用域鏈直至頂級作用域,而局部變數的存取效率則會更快更高,因此在局部作用域中高頻率使用一些全域物件時可以將其導入到局部作用域中,例如:

  //1、作为参数传入模块
  (function(window,$){
      var xxx = window.xxx;
      $("#xxx1").xxx();
      $("#xxx2").xxx();
  })(window,jQuery);

  //2、暂存到局部变量
  function(){
     var doc = document;
     var global = window.global;
 }
登入後複製

2、eval以及類別eval問題

我們都知道eval可以將一段字串當做js程式碼來執行處理,據說使用eval執行的程式碼比不使用eval的程式碼慢100倍以上(具體效率我沒有測試,有興趣同學可以測試一下)

JavaScript 程式碼在執行前會進行類似「預先編譯」的操作:首先會建立一個目前執行環境下的活動對象,並將那些以var 申明的變數設為活動物件的屬性,但此時這些變數的賦值都是undefined,並將那些以function 定義的函數也加入為活動物件的屬性,而且它們的值正是函數的定義。但是,如果你使用了“eval”,則“eval”中的程式碼(實際上為字串)無法預先識別其上下文,無法事先解析和最佳化,即無法進行預編譯的操作。所以,其效能也會大幅降低

其實作在大家一般都很少會用eval了,這裡我想說的是兩個類別eval的場景(new Function{} ,setTimeout,setInterver)

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

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

(new Function("alert(1)"))();
登入後複製

上述幾種型別程式碼執行效率都會比較低,因此建議直接傳入匿名方法、或方法的引用給setTimeout方法

3、閉包結束後釋放掉不再被引用的變數

var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //****其它变量
    //***一些运算
    var res = function(){
        alert(a.name);
    }
    return res;
})()
登入後複製

上述程式碼中變數f的回傳值是由一個立即執行函數構成的閉包中傳回的方法res,該變數保留了對於這個閉包中所有變數(a,b,c等)的引用,因此這兩個變數會一直駐留在記憶體空間中,尤其是對於dom元素的引用對記憶體的消耗會很大,而我們在res中只使用到了a變數的值,因此,在閉包返回之前我們可以將其它變數釋放

var f = (function(){
    var a = {name:"var3"};
    var b = ["var1","var2"];
    var c = document.getElementByTagName("li");
    //****其它变量
    //***一些运算
    //闭包返回前释放掉不再使用的变量
    b = c = null;
    var res = function(){
        alert(a.name);
        }
    return res;
})()
登入後複製

Js操作dom的效率

在web開發過程中,前端執行效率的瓶頸往往都是在dom操作上面,dom操作是一件很耗性能的事情,如何在dom操作過程中盡量節約效能呢?

1、減少reflow

什麼是reflow?

當 DOM 元素的屬性改變 (如 color) 時, 瀏覽器會通知 render 重新描繪對應的元素, 此程序稱為 repaint。

如果該次變更涉及元素佈局(如width), 瀏覽器則拋棄原有屬性, 重新計算並把結果傳遞給render 以重新描繪頁面元素, 此過程稱為reflow。

減少reflow的方法

  1. 先將元素從document中刪除,完成修改後再把元素放回原來的位置(當對某元素及其子元素進行大量reflow操作時,1,2兩種方法效果才會比較明顯)

  2. #將元素的display設為”none”,完成修改後再把display修改為原來的值

  3. 修改多個樣式屬性時定義class類別代替多次修改style屬性(for certain同學推薦)

  4. 大量新增元素到頁面時使用documentFragment

#例如

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

上述程式碼會多次操作dom,效率比較低,可以改為下面的形式創建documentFragment,將所有元素加入到docuemntFragment不會改變dom結構,最後將其添加到頁面,只進行了一次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);
登入後複製

2、暂存dom状态信息

当代码中需要多次访问元素的状态信息,在状态不变的情况下我们可以将其暂存到变量中,这样可以避免多次访问dom带来内存的开销,典型的例子就是:

var lis = document.getElementByTagName("li");
for(var i=1;i<lis.length;i++){
    //***
}
上述方式会在每一次循环都去访问dom元素,我们可以简单将代码优化如下
var lis = document.getElementByTagName("li");
for(var i=1,j=lis.length ;i<j;i++){
    //***
}
登入後複製

3、缩小选择器的查找范围

查找dom元素时尽量避免大面积遍历页面元素,尽量使用精准选择器,或者指定上下文以缩小查找范围,以jquery为例

  • 少用模糊匹配的选择器:例如$("[name*=&#39;_fix&#39;]"),多用诸如id以及逐步缩小范围的复合选择器$("li.active")

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

4、使用事件委托

使用场景:一个有大量记录的列表,每条记录都需要绑定点击事件,在鼠标点击后实现某些功能,我们通常的做法是给每条记录都绑定监听事件,这种做法会导致页面会有大量的事件监听器,效率比较低下。

基本原理:我们都知道dom规范中事件是会冒泡的,也就是说在不主动阻止事件冒泡的情况下任何一个元素的事件都会按照dom树的结构逐级冒泡至顶端。而event对象中也提供了event.target(IE下是srcElement)指向事件源,因此我们即使在父级元素上监听该事件也可以找到触发该事件的最原始的元素,这就是委托的基本原理。废话不多说,上示例

$("ul li").bind("click",function(){
    alert($(this).attr("data"));
})
登入後複製

上述写法其实是给所有的li元素都绑定了click事件来监听鼠标点击每一个元素的事件,这样页面上会有大量的事件监听器。

根据上面介绍的监听事件的原理我们来改写一下

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

这样一来,我们就可以只添加一个事件监听器去捕获所有li上触发的事件,并做出相应的操作。

当然,我们不必每次都做事件源的判断工作,可以将其抽象一下交给工具类来完成。jquery中的delegate()方法就实现了该功能

语法是这样的$(selector).delegate(childSelector,event,data,function),例如:

$("p").delegate("button","click",function(){
  $("p").slideToggle();
});
登入後複製
参数说明(引自w3school)
登入後複製
参数 描述
childSelector 必需。规定要附加事件处理程序的一个或多个子元素。
event 必需。规定附加到元素的一个或多个事件。由空格分隔多个事件值。必须是有效的事件。
data 可选。规定传递到函数的额外数据。
function 必需。规定当事件发生时运行的函数。

 





Tips:事件委托还有一个好处就是,即使在事件绑定之后动态添加的元素上触发的事件同样可以监听到哦,这样就不用在每次动态加入元素到页面后都为其绑定事件了










以上是簡單介紹JavaScript的執行效率的詳細內容。更多資訊請關注PHP中文網其他相關文章!

本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover

AI Clothes Remover

用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱門文章

<🎜>:泡泡膠模擬器無窮大 - 如何獲取和使用皇家鑰匙
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
北端:融合系統,解釋
3 週前 By 尊渡假赌尊渡假赌尊渡假赌
Mandragora:巫婆樹的耳語 - 如何解鎖抓鉤
3 週前 By 尊渡假赌尊渡假赌尊渡假赌

熱工具

記事本++7.3.1

記事本++7.3.1

好用且免費的程式碼編輯器

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

禪工作室 13.0.1

禪工作室 13.0.1

強大的PHP整合開發環境

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

SublimeText3 Mac版

SublimeText3 Mac版

神級程式碼編輯軟體(SublimeText3)

熱門話題

Java教學
1666
14
CakePHP 教程
1425
52
Laravel 教程
1324
25
PHP教程
1272
29
C# 教程
1251
24
如何使用WebSocket和JavaScript實現線上語音辨識系統 如何使用WebSocket和JavaScript實現線上語音辨識系統 Dec 17, 2023 pm 02:54 PM

如何使用WebSocket和JavaScript實現線上語音辨識系統引言:隨著科技的不斷發展,語音辨識技術已成為了人工智慧領域的重要組成部分。而基於WebSocket和JavaScript實現的線上語音辨識系統,具備了低延遲、即時性和跨平台的特點,成為了廣泛應用的解決方案。本文將介紹如何使用WebSocket和JavaScript來實現線上語音辨識系

WebSocket與JavaScript:實現即時監控系統的關鍵技術 WebSocket與JavaScript:實現即時監控系統的關鍵技術 Dec 17, 2023 pm 05:30 PM

WebSocket與JavaScript:實現即時監控系統的關鍵技術引言:隨著互聯網技術的快速發展,即時監控系統在各個領域中得到了廣泛的應用。而實現即時監控的關鍵技術之一就是WebSocket與JavaScript的結合使用。本文將介紹WebSocket與JavaScript在即時監控系統中的應用,並給出程式碼範例,詳細解釋其實作原理。一、WebSocket技

如何利用JavaScript和WebSocket實現即時線上點餐系統 如何利用JavaScript和WebSocket實現即時線上點餐系統 Dec 17, 2023 pm 12:09 PM

如何利用JavaScript和WebSocket實現即時線上點餐系統介紹:隨著網路的普及和技術的進步,越來越多的餐廳開始提供線上點餐服務。為了實現即時線上點餐系統,我們可以利用JavaScript和WebSocket技術。 WebSocket是一種基於TCP協定的全雙工通訊協議,可實現客戶端與伺服器的即時雙向通訊。在即時線上點餐系統中,當使用者選擇菜餚並下訂單

如何使用WebSocket和JavaScript實現線上預約系統 如何使用WebSocket和JavaScript實現線上預約系統 Dec 17, 2023 am 09:39 AM

如何使用WebSocket和JavaScript實現線上預約系統在當今數位化的時代,越來越多的業務和服務都需要提供線上預約功能。而實現一個高效、即時的線上預約系統是至關重要的。本文將介紹如何使用WebSocket和JavaScript來實作一個線上預約系統,並提供具體的程式碼範例。一、什麼是WebSocketWebSocket是一種在單一TCP連線上進行全雙工

JavaScript與WebSocket:打造高效率的即時天氣預報系統 JavaScript與WebSocket:打造高效率的即時天氣預報系統 Dec 17, 2023 pm 05:13 PM

JavaScript和WebSocket:打造高效的即時天氣預報系統引言:如今,天氣預報的準確性對於日常生活以及決策制定具有重要意義。隨著技術的發展,我們可以透過即時獲取天氣數據來提供更準確可靠的天氣預報。在本文中,我們將學習如何使用JavaScript和WebSocket技術,來建立一個高效的即時天氣預報系統。本文將透過具體的程式碼範例來展示實現的過程。 We

簡易JavaScript教學:取得HTTP狀態碼的方法 簡易JavaScript教學:取得HTTP狀態碼的方法 Jan 05, 2024 pm 06:08 PM

JavaScript教學:如何取得HTTP狀態碼,需要具體程式碼範例前言:在Web開發中,經常會涉及到與伺服器進行資料互動的場景。在與伺服器進行通訊時,我們經常需要取得傳回的HTTP狀態碼來判斷操作是否成功,並根據不同的狀態碼來進行對應的處理。本篇文章將教你如何使用JavaScript來取得HTTP狀態碼,並提供一些實用的程式碼範例。使用XMLHttpRequest

javascript如何使用insertBefore javascript如何使用insertBefore Nov 24, 2023 am 11:56 AM

用法:在JavaScript中,insertBefore()方法用於在DOM樹中插入一個新的節點。這個方法需要兩個參數:要插入的新節點和參考節點(即新節點將要插入的位置的節點)。

JavaScript與WebSocket:打造高效率的即時影像處理系統 JavaScript與WebSocket:打造高效率的即時影像處理系統 Dec 17, 2023 am 08:41 AM

JavaScript是一種廣泛應用於Web開發的程式語言,而WebSocket則是一種用於即時通訊的網路協定。結合二者的強大功能,我們可以打造一個高效率的即時影像處理系統。本文將介紹如何利用JavaScript和WebSocket來實作這個系統,並提供具體的程式碼範例。首先,我們需要明確指出即時影像處理系統的需求和目標。假設我們有一個攝影機設備,可以擷取即時的影像數

See all articles