搜尋
首頁web前端js教程使用Function.apply()的參數數組化來提高 JavaScript程式效能的技巧_javascript技巧

我們再來聊聊Function.apply() 在提升程式效能方面的技巧。

我們先從 Math.max() 函數說起, Math.max後面可以接著任何個參數,最後回傳所有參數中的最大值。


alert(Math.max(5,8))  //8 
alert(Math.max(5,7,9,3,1,6))  //9 

但是在很多情況下,我們需要找出陣列中最大的元素。

var arr=[5,7,9,1] 
alert(Math.max(arr))  //  这样却是不行的。一定要这样写 
function getMax(arr){ 
  var arrLen=arr.length; 
  for(var i=0,ret=arr[0];i<arrLen;i++){ 
    ret=Math.max(ret,arr[i]);     
  } 
  return ret; 
}  

這樣寫麻煩而且低效。如果用 apply呢,看代碼:

function getMax2(arr){ 
  return Math.max.apply(null,arr) 
} 

兩段程式碼達到了同樣的目的,但是getMax2卻優雅,高效,簡潔得多。

看效能測驗:

getMax效能測試

var myArr=new Array() 
function fillRnd(arrLen){ //填入 arrLen个1-10的随机数字到数组 
  for(var i=0,arr=[];i<arrLen;i++){ 
    arr[i]=Math.ceil(Math.random()*10) 
  } 
  return arr 
} 
function getMax(arr){ 
  var arrLen=arr.length; 
  for(var i=0,ret=arr[0];i<arrLen;i++){ 
    ret=Math.max(ret,arr[i]);     
  } 
  return ret; 
} 
function getMax2(arr){ 
  return Math.max.apply(null,arr) 
} 
myArr=fillRnd(20*10000) //生成20万个随机数填到数组 
var t1=new Date() 
var max1=getMax(myArr) 
var t2=new Date() 
var max2=getMax2(myArr) 
var t3=new Date() 
if (max1!==max2) alert("error") 
alert([t3-t2,t2-t1])  //在我机器上 96,464 .不同的机器,结果可能有差异 

經過20萬個資料的比較, getMax2 時間為 96ms 而 getmax時間為464。 兩者相差5倍

再例如數組的push方法。

var arr1=[1,3,4]; 
var arr2=[3,4,5];

如果我們要把 arr2展開,然後一個一個追加到 arr1中去,最後讓 arr1=[1,3,4,3,4,5]

arr1.push(arr2) 顯然是不行的。 因為這樣做會得到 [1,3,4, [3,4,5] ] 

我們只能用一個循環去一個一個的push (當然也可以用 arr1.concat(arr2) 但是concat方法並沒有改變 arr1本身) 

var arrLen=arr2.length 
for(var i=0;i<arrLen;i++){ 
  arr1.push(arr2[i]) 
}

自從有了 Apply ,事情就變得如此簡單

Array.prototype.push.apply(arr1,arr2) 

附:如何最佳化JavaScript腳本的效能

隨著網路的發展,網路速度和機器速度的提高,越來越多的網站用到了豐富客戶端技術。而現在Ajax則是最受歡迎的一種方式。 JavaScript是一種解釋型語言,所以能無法達到和C/Java之類的水平,限制了它能在客戶端所做的事情,為了能改進他的性能,我想基於我以前給JavaScript做過的很多測試來談談自己的經驗,希望能幫助大家改進自己的JavaScript腳本效能。

語言層次方面

循環

循環是很常用的一個控制結構,大部分東西要依靠它來完成,在JavaScript中,我們可以使用for(;;),while(),for(in)三種循環,事實上,這三種迴圈中for(in)的效率極差,因為他需要查詢散列鍵,只要可以就應該盡量少用。 for(;;)和while迴圈的表現應該說基本(平常使用時)等價。

而事實上,如何使用這兩個循環,則有很大講究。我在測試中有些很有意思的情況,請見附錄。最後得出的結論是:

如果是循環變數遞增或遞減,不要單獨對循環變數賦值,應該在它最後一次讀取的時候使用嵌套的++或—操作符。

如果要與陣列的長度作比較,應該事先把陣列的length屬性放入一個局部變數中,減少查詢次數。

局部變數與全域變數

局部變數的速度要比全域變數的存取速度更快,因為全域變數其實是全域物件的成員,而局部變數是放在函數的堆疊當中的。

不使用Eval

使用eval相當於在運行時再次呼叫解釋引擎對內容進行運行,需要消耗大量時間。這時候使用JavaScript所支援的閉包可以實現函數模版(關於閉包的內容請參考函數式程式設計的內容)

減少物件查找

因為JavaScript的解釋性,所以a.b.c.d.e,需要進行至少4次查詢操作,先檢查a再檢查a中的b,再檢查b中的c,如此往下。所以如果這樣的表達式重複出現,只要可能,應該盡量少出現這樣的表達式,可以利用局部變量,把它放入一個臨時的地方進行查詢。

這一點可以和循環結合起來,因為我們常常要根據字串、數組的長度進行循環,而通常這個長度是不變的,比如每次查詢a.length,就要額外進行一個操作,而預先把var len=a.length,則少了一次查詢。

字串連線

如果是追加字串,最好使用s+=anotherStr操作,而不是要使用s=s+anotherStr。

如果要連接多個字串,應該少使用+=,如

s+=a;s+=b;s+=c;應該寫成
s+=a + b + c;而如果是收集字串,例如多次對同一個字串進行+=操作的話,最好使用一個快取。怎麼用呢?使用JavaScript數組來收集,最後使用join方法連接起來,如下

var buf = new Array();for(var i = 0; i < 100; i++){ buf.push(i.toString());}var all = buf.join("");类型转换

型別轉換是大家常犯的錯誤,因為JavaScript是動態型別語言,你不能指定變數的型別。

1. 把數字轉換成字串,應用"" + 1,雖然看起來比較醜一點,但事實上這個效率是最高的,性能上來說:
("" +) > String() > .toString() > new String()

這條其實和下面的「直接量」有點類似,盡量使用編譯時就能使用的內部操作要比執行時使用的使用者操作要快。

String()屬於內部函數,所以速度很快,而.toString()要查詢原型中的函數,所以速度遜色一些,new String()用於傳回精確的副本。

2. 浮點數轉換成整數型,這個比較容易出錯,很多人喜歡使用parseInt(),其實parseInt()是用來將字串轉換成數字,而不是浮點數和整數之間的轉換,我們應該使用Math.floor()或Math.round()。
另外,和第二節的對象查找的問題不一樣,Math是內部對象,所以Math.floor()其實並沒有太多查詢方法和呼叫的時間,速度是最快的。

3. 對於自訂的對象,如果定義了toString()方法來進行類型轉換的話,推薦明確調用toString(),因為內部的操作在嘗試所有可能性之後,會嘗試對象的toString()方法嘗試能否轉換為String,所以直接呼叫這個方法效率會更高

使用直接量

其實這個影響倒比較小,可以忽略。什麼叫做使用直接量,例如,JavaScript支援使用[param,param,param,...]來直接表達一個數組,以往我們都使用new Array(param,param,...),使用前者是引擎直接解釋的,後者要呼叫一個Array內部構造器,所以要稍微快一點點。

同樣,var foo = {}的方式也比var foo = new Object();快,var reg = /../;要比var reg=new RegExp()快。

字串遍歷運算

對字串進行循環操作,譬如替換、查找,應使用正規表示式,因為本身JavaScript的循環速度就比較慢,而正則表達式的操作是用C寫成的語言的API,性能很好。

高階物件

自訂高階物件和Date、RegExp物件在建構時都會消耗大量時間。如果可以重複使用,應採用快取的方式。

DOM相關

插入HTML

很多人喜歡在JavaScript中使用document.write來為頁面產生內容。事實上這樣的效率較低,如果需要直接插入HTML,可以找一個容器元素,例如指定一個div或span,並設定他們的innerHTML來將自己的HTML程式碼插入頁面中。

物件查詢

使用[“”]查詢要比.items()更快,這和前面的減少物件查找的思路是一樣的,呼叫.items()增加了一次查詢和函數的呼叫。

建立DOM節點

通常我們可能會使用字串直接寫HTML來建立節點,其實這樣做

無法保證程式碼的有效性

字串操作效率低

所以應該是用document.createElement()方法,而如果文件中存在現成的樣板節點,應該是用cloneNode()方法,因為使用createElement()方法之後,你需要設定多次元素的屬性,使用cloneNode()則可以減少屬性的設定次數-同樣如果需要建立很多元素,應該先準備一個樣板節點。

定時器

如果針對的是不斷運作的程式碼,不應該使用setTimeout,而應該是用setInterval。 setTimeout每次要重新設定計時器。

其他

腳本引擎

根據我測試Microsoft的JScript的效率較Mozilla的Spidermonkey要差很多,無論是執行速度還是記憶體管理上,因為JScript現在基本上也不更新了。但SpiderMonkey不能使用ActiveXObject

檔案最佳化

檔案最佳化也是一個很有效的手段,刪除所有的空格和註釋,把程式碼放入一行內,可以加快下載的速度,注意,是下載的速度而不是解析的速度,如果是本地,註解和空格並不會影響解釋和執行速度。

總結

本文總結了我在JavaScript程式設計中所找到的一些提升JavaScript運行效能的方法,其實這些經驗都是基於幾個原則:

直接拿手邊現成的東西比較快,如局部變數比全域變數快,直接量比執行時間構造物件快等等。

盡量少減少執行次數,例如先快取需要多次查詢的。

盡可能使用語言內建的功能,例如字串連結。

盡量使用系統提供的API,因為這些API是編譯好的二進位程式碼,執行效率很高

同时,一些基本的算法上的优化,同样可以用在JavaScript中,比如运算结构的调整,这里就不再赘述了。但是由于JavaScript是解释型的,一般不会在运行时对字节码进行优化,所以这些优化仍然是很重要的。

当然,其实这里的一些技巧同样使用在其他的一些解释型语言中,大家也可以进行参考。

由于是以前做过的测试,测试代码已经不全,我补充了一部分如下:

var print; 
if(typeof document != "undefined" ){ 
  print = function(){ 
document.write(arguments[0]); 
} 
}else if(typeof WScript != "undefined" ){ 
  print = function(){ 
    WScript.Echo(arguments[0],arguments[1],arguments[2]); 
  } 
} 
function empty(){ 
} 
function benchmark(f){ 
  var i = 0; 
  var start = (new Date()).getTime(); 
  while(i < pressure){ 
    f(i++); 
  } 
  var end = (new Date()).getTime(); 
  WScript.Echo(end-start); 
} 
/* 
i=0 
start = (new Date()).getTime(); 
while(i < 60000){ 
  c = [i,i,i,i,i,i,i,i,i,i]; 
  i++; 
} 
end = (new Date()).getTime(); 
WScript.Echo(end-start); 
i=0 
start = (new Date()).getTime(); 
while(i < 60000){ 
  c = new Array(i,i,i,i,i,i,i,i,i,i); 
  i++; 
} 
var end = (new Date()).getTime(); 
WScript.Echo(end-start); 
*/ 
function internCast(i){ 
  return "" + i; 
} 
function StringCast(i){ 
  return String(i) 
} 
function newStringCast(i){ 
  return new String(i) 
} 
function toStringCast(i){ 
  return i.toString(); 
} 
function ParseInt(){ 
  return parseInt(j); 
} 
function MathFloor(){ 
  return Math.floor(j); 
} 
function Floor(){ 
  return floor(j); 
} 
var pressure = 50000; 
var a = ""; 
var floor = Math.floor; 
j = 123.123; 
print("-------------\nString Conversion Test"); 
print("The empty:", benchmark(empty)); 
print("intern:", benchmark(internCast)); 
print("String:"); 
benchmark(StringCast); 
print("new String:"); 
benchmark(newStringCast); 
print("toString:"); 
benchmark(toStringCast); 
print("-------------\nFloat to Int Conversion Test"); 
print("parseInt"); 
benchmark(ParseInt); 
print("Math.floor"); 
benchmark(MathFloor); 
print("floor") 
benchmark(Floor); 
function newObject(){ 
  return new Object(); 
} 
function internObject(){ 
  return {}; 
} 
print("------------\nliteral Test"); 
print("runtime new object", benchmark(newObject)); 
print("literal object", benchmark(internObject));  

附录2

代码1:

for(var i=0;i<100;i++){ 
    arr[i]=0; 
  }

代码2:

 var i = 0; 
  while(i < 100){ 
    arr[i++]=0; 
  } 

 代码3: 

 var i = 0; 
  while(i < 100){ 
    arr[i]=0; 
    i++; 
  }

 在firefox下测试这两段代码,结果是代码2优于代码1和3,而代码1一般优于代码3,有时会被代码3超过;而在IE 6.0下,测试压力较大的时候(如测试10000次以上)代码2和3则有时候优于代码1,有时候就会远远落后代码1,而在测试压力较小(如5000次),则代码2>代码3>代码1。

代码4:

var i = 0; 
  var a; 
  while(i < 100){ 
    a = 0; 
    i++; 
  } 

代码5:

 var a; 
  for(var i=0;i<100;i++){ 
    a = 0; 
  } 

上面两段代码在Firefox和IE下测试结果都是性能接近的。

代码6:

  var a; 
  var i=0; 
  while(i<100){ 
    a=i; 
    i++; 
  } 

代码7:

 var a; 
  var i=0; 
  while(i<100){ 
    a=i++; 
  } 

代码8:

 var a; 
  for(var i=0;i<100;i++){ 
    a = i; 
  } 

代码9:

 var a; 
  for(var i=0;i<100;){ 
    a = i++; 
  } 

这四段代码在Firefox下6和8的性能接近,7和9的性能接近,而6, 8

最后我们来看一下空循环

代码10: 

for(var i=0;i<100;i++){  } 

代码11:

  var i; 
  while(i<100){    i++;  } 

最后的测试出现了神奇的结果,Firefox下代码10所花的时间与代码11所花的大约是24:1。所以它不具备参考价值,于是我没有放在一开始给大家看。

陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
在JavaScript中替換字符串字符在JavaScript中替換字符串字符Mar 11, 2025 am 12:07 AM

JavaScript字符串替換方法詳解及常見問題解答 本文將探討兩種在JavaScript中替換字符串字符的方法:在JavaScript代碼內部替換和在網頁HTML內部替換。 在JavaScript代碼內部替換字符串 最直接的方法是使用replace()方法: str = str.replace("find","replace"); 該方法僅替換第一個匹配項。要替換所有匹配項,需使用正則表達式並添加全局標誌g: str = str.replace(/fi

構建您自己的Ajax Web應用程序構建您自己的Ajax Web應用程序Mar 09, 2025 am 12:11 AM

因此,在這裡,您準備好了解所有稱為Ajax的東西。但是,到底是什麼? AJAX一詞是指用於創建動態,交互式Web內容的一系列寬鬆的技術。 Ajax一詞,最初由Jesse J創造

如何創建和發布自己的JavaScript庫?如何創建和發布自己的JavaScript庫?Mar 18, 2025 pm 03:12 PM

文章討論了創建,發布和維護JavaScript庫,專注於計劃,開發,測試,文檔和促銷策略。

如何在瀏覽器中優化JavaScript代碼以進行性能?如何在瀏覽器中優化JavaScript代碼以進行性能?Mar 18, 2025 pm 03:14 PM

本文討論了在瀏覽器中優化JavaScript性能的策略,重點是減少執行時間並最大程度地減少對頁面負載速度的影響。

jQuery矩陣效果jQuery矩陣效果Mar 10, 2025 am 12:52 AM

將矩陣電影特效帶入你的網頁!這是一個基於著名電影《黑客帝國》的酷炫jQuery插件。該插件模擬了電影中經典的綠色字符特效,只需選擇一張圖片,插件就會將其轉換為充滿數字字符的矩陣風格畫面。快來試試吧,非常有趣! 工作原理 插件將圖片加載到畫布上,讀取像素和顏色值: data = ctx.getImageData(x, y, settings.grainSize, settings.grainSize).data 插件巧妙地讀取圖片的矩形區域,並利用jQuery計算每個區域的平均顏色。然後,使用

如何使用瀏覽器開發人員工具有效調試JavaScript代碼?如何使用瀏覽器開發人員工具有效調試JavaScript代碼?Mar 18, 2025 pm 03:16 PM

本文討論了使用瀏覽器開發人員工具的有效JavaScript調試,專注於設置斷點,使用控制台和分析性能。

如何構建簡單的jQuery滑塊如何構建簡單的jQuery滑塊Mar 11, 2025 am 12:19 AM

本文將引導您使用jQuery庫創建一個簡單的圖片輪播。我們將使用bxSlider庫,它基於jQuery構建,並提供許多配置選項來設置輪播。 如今,圖片輪播已成為網站必備功能——一圖胜千言! 決定使用圖片輪播後,下一個問題是如何創建它。首先,您需要收集高質量、高分辨率的圖片。 接下來,您需要使用HTML和一些JavaScript代碼來創建圖片輪播。網絡上有很多庫可以幫助您以不同的方式創建輪播。我們將使用開源的bxSlider庫。 bxSlider庫支持響應式設計,因此使用此庫構建的輪播可以適應任何

如何使用Angular上傳和下載CSV文件如何使用Angular上傳和下載CSV文件Mar 10, 2025 am 01:01 AM

數據集對於構建API模型和各種業務流程至關重要。這就是為什麼導入和導出CSV是經常需要的功能。在本教程中,您將學習如何在Angular中下載和導入CSV文件

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

AI Hentai Generator

AI Hentai Generator

免費產生 AI 無盡。

熱門文章

R.E.P.O.能量晶體解釋及其做什麼(黃色晶體)
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.最佳圖形設置
3 週前By尊渡假赌尊渡假赌尊渡假赌
R.E.P.O.如果您聽不到任何人,如何修復音頻
3 週前By尊渡假赌尊渡假赌尊渡假赌

熱工具

SublimeText3 英文版

SublimeText3 英文版

推薦:為Win版本,支援程式碼提示!

SecLists

SecLists

SecLists是最終安全測試人員的伙伴。它是一個包含各種類型清單的集合,這些清單在安全評估過程中經常使用,而且都在一個地方。 SecLists透過方便地提供安全測試人員可能需要的所有列表,幫助提高安全測試的效率和生產力。清單類型包括使用者名稱、密碼、URL、模糊測試有效載荷、敏感資料模式、Web shell等等。測試人員只需將此儲存庫拉到新的測試機上,他就可以存取所需的每種類型的清單。

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SAP NetWeaver Server Adapter for Eclipse

SAP NetWeaver Server Adapter for Eclipse

將Eclipse與SAP NetWeaver應用伺服器整合。

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版