Rumah  >  Artikel  >  hujung hadapan web  >  Petua untuk meningkatkan prestasi atur cara JavaScript menggunakan tatasusunan parameter petua Function.apply()_javascript

Petua untuk meningkatkan prestasi atur cara JavaScript menggunakan tatasusunan parameter petua Function.apply()_javascript

WBOY
WBOYasal
2016-05-16 15:24:001335semak imbas

Mari kita bincangkan tentang kemahiran Function.apply() dalam meningkatkan prestasi program.

Mari mulakan dengan fungsi Math.max() boleh diikuti oleh sebarang bilangan parameter, dan akhirnya mengembalikan nilai maksimum antara semua parameter.

Contohnya

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

Tetapi dalam banyak kes, kita perlu mencari elemen terbesar dalam tatasusunan.

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

Menulis seperti ini menyusahkan dan tidak cekap. Jika anda menggunakan apply, lihat pada kod:

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

Dua keping kod mencapai tujuan yang sama, tetapi getMax2 jauh lebih elegan, cekap dan ringkas.

Lihat ujian prestasi:

ujian prestasi 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 .不同的机器,结果可能有差异 

Dengan membandingkan 200,000 data, masa getMax2 ialah 96ms dan masa getmax ialah 464. Perbezaan antara keduanya ialah 5 kali ganda

Contoh lain ialah kaedah tolak tatasusunan.

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

Jika kita ingin mengembangkan arr2, dan kemudian tambah pada arr1 satu demi satu, akhirnya biarkan arr1=[1,3,4,3,4,5]

arr1.push(arr2) jelas tidak berfungsi. Kerana melakukan ini akan mendapat [1,3,4, [3,4,5] ]

Kami hanya boleh menggunakan gelung untuk menolak satu demi satu (sudah tentu anda juga boleh menggunakan arr1.concat(arr2) tetapi kaedah concat tidak mengubah arr1 itu sendiri)

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

Memandangkan kami telah Memohon , perkara menjadi sangat mudah

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

Lampiran: Cara mengoptimumkan prestasi skrip JavaScript

Dengan pembangunan Internet dan peningkatan kelajuan rangkaian dan kelajuan mesin, semakin banyak tapak web menggunakan teknologi pelanggan yang kaya. Sekarang Ajax adalah kaedah yang paling popular. JavaScript ialah bahasa yang ditafsirkan, jadi sama ada ia boleh mencapai tahap yang sama seperti C/Java mengehadkan perkara yang boleh dilakukan pada klien Untuk meningkatkan prestasinya, saya ingin membina apa yang telah saya lakukan untuk JavaScript sebelum ini bercakap tentang pengalaman saya sendiri, dengan harapan dapat membantu semua orang meningkatkan prestasi skrip JavaScript mereka.

Tahap bahasa

Gelung

Gelung ialah struktur kawalan yang biasa digunakan kebanyakan perkara bergantung padanya untuk melengkapkan Dalam JavaScript, kita boleh menggunakan tiga jenis gelung: for(;;), while(), dan for(in). ini Kecekapan for(in) antara tiga jenis gelung adalah amat lemah kerana ia perlu menanyakan kunci cincang, jadi ia harus digunakan sesedikit mungkin jika boleh. Prestasi gelung for(;;) dan while hendaklah dikatakan pada asasnya setara (apabila digunakan dalam kegunaan harian).

Malah, cara menggunakan kedua-dua gelung ini adalah sangat khusus. Saya mempunyai beberapa situasi yang menarik dalam ujian saya, lihat lampiran. Kesimpulan akhir ialah:

Jika pembolehubah gelung bertambah atau berkurangan, jangan tetapkan nilai kepada pembolehubah gelung sahaja Anda harus menggunakan operator bersarang atau - apabila ia dibaca kali terakhir.

Jika anda ingin membandingkan dengan panjang tatasusunan, anda harus meletakkan atribut panjang tatasusunan ke dalam pembolehubah setempat terlebih dahulu untuk mengurangkan bilangan pertanyaan.

Pembolehubah setempat dan pembolehubah global

Pembolehubah setempat diakses lebih cepat daripada pembolehubah global, kerana pembolehubah global sebenarnya adalah ahli objek global, manakala pembolehubah tempatan diletakkan pada timbunan fungsi.

Jangan gunakan Eval

Menggunakan eval adalah sama dengan memanggil enjin tafsiran sekali lagi untuk menjalankan kandungan pada masa jalan, yang memerlukan banyak masa. Pada masa ini, templat fungsi boleh dilaksanakan menggunakan penutupan yang disokong oleh JavaScript (untuk butiran mengenai penutupan, sila rujuk kandungan yang berkaitan tentang pengaturcaraan berfungsi)

Kurangkan carian objek

Oleh sebab kebolehtafsiran JavaScript, a.b.c.d.e memerlukan sekurang-kurangnya 4 operasi pertanyaan Mula-mula semak a, kemudian tandakan b dalam a, kemudian semak c dalam b, dan seterusnya. Oleh itu, jika ungkapan tersebut muncul berulang kali, ungkapan tersebut hendaklah disimpan sejarang mungkin sebanyak mungkin Anda boleh menggunakan pembolehubah setempat untuk meletakkannya di tempat sementara untuk membuat pertanyaan.

Ini boleh digabungkan dengan gelung, kerana kita selalunya perlu menggelung berdasarkan panjang rentetan dan tatasusunan, dan biasanya panjang ini tidak berubah Contohnya, setiap kali a.length disoal, operasi tambahan diperlukan dan Jika anda menetapkan var len=a.length terlebih dahulu, akan kurang satu pertanyaan.

Gabungan rentetan

Jika anda menambahkan rentetan, sebaiknya gunakan operasi s =anotherStr daripada menggunakan s=s anotherStr.

Jika anda ingin menggabungkan berbilang rentetan, anda harus menggunakan kurang =, seperti

s =a;s =b;s =c; hendaklah ditulis sebagai
s =a b c; dan jika anda mengumpul rentetan, seperti menjalankan = operasi pada rentetan yang sama beberapa kali, sebaiknya gunakan cache. Bagaimana cara menggunakannya? Gunakan tatasusunan JavaScript untuk mengumpul, dan akhirnya gunakan kaedah gabungan untuk menyambung, seperti berikut

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

Penukaran jenis ialah kesilapan biasa yang dilakukan oleh semua orang, kerana JavaScript ialah bahasa yang ditaip secara dinamik dan anda tidak boleh menentukan jenis pembolehubah.

1. Tukar nombor kepada rentetan dan gunakan "" 1. Walaupun ia kelihatan agak hodoh, sebenarnya ini adalah yang paling cekap, dari segi prestasi:
("" ) > String() >

Ini sebenarnya agak serupa dengan "kuantiti langsung" di bawah Cuba gunakan operasi dalaman yang boleh digunakan pada masa penyusunan agar lebih pantas daripada operasi pengguna yang digunakan pada masa jalan.

String() ialah fungsi dalaman, jadi ia sangat pantas, manakala .toString() menanyakan fungsi dalam prototaip, jadi ia tidak secepat String() baru digunakan untuk mengembalikan salinan tepat.

2. Menukar nombor titik terapung kepada integer lebih terdedah kepada ralat Ramai orang suka menggunakan parseInt() digunakan untuk menukar rentetan kepada nombor, bukan antara nombor titik terapung dan integer harus menggunakan Math.floor() atau Math.round().

Selain itu, tidak seperti masalah dalam carian objek dalam Bahagian 2, Math ialah objek dalaman, jadi Math.floor() sebenarnya tidak mempunyai banyak kaedah pertanyaan dan masa panggilan, dan merupakan yang terpantas.

3. Untuk objek tersuai, jika kaedah toString() ditakrifkan untuk penukaran jenis, adalah disyorkan untuk memanggil secara eksplisit keString(), kerana operasi dalaman akan mencuba objek toString() selepas mencuba semua kemungkinan sama ada ia boleh ditukar kepada String, jadi memanggil kaedah ini secara langsung akan menjadi lebih cekap

Gunakan kuantiti langsung

Malah, impak ini agak kecil dan boleh diabaikan. Apakah yang dimaksudkan dengan menggunakan kuantiti langsung? Contohnya, JavaScript menyokong penggunaan [param, param, param,...] untuk menyatakan tatasusunan secara langsung. . Menggunakan yang pertama ditafsirkan secara langsung oleh enjin , yang terakhir memanggil pembina dalaman Array, jadi ia lebih pantas.


Begitu juga, var foo = {} adalah lebih pantas daripada var foo = new Object();, dan var reg = /../; lebih pantas daripada var reg=new RegExp().

Operasi rentas rentetan

Untuk melaksanakan operasi gelung pada rentetan, seperti penggantian dan carian, ungkapan biasa harus digunakan, kerana kelajuan gelung JavaScript itu sendiri adalah agak perlahan dan pengendalian ungkapan biasa ialah API yang ditulis dalam C, dan prestasinya adalah sangat baik.

Objek Lanjutan

Objek lanjutan tersuai dan objek Tarikh dan RegExp akan memakan banyak masa semasa pembinaan. Jika ia boleh digunakan semula, caching harus digunakan.

berkaitan DOM

Sisipkan HTML

Ramai orang suka menggunakan document.write dalam JavaScript untuk menjana kandungan untuk halaman tersebut. Malah, ini kurang cekap Jika anda perlu memasukkan HTML secara langsung, anda boleh mencari elemen bekas, seperti menentukan div atau span, dan menetapkan innerHTML mereka untuk memasukkan kod HTML anda sendiri ke dalam halaman.

Pertanyaan Objek

Menggunakan [""] untuk membuat pertanyaan adalah lebih pantas daripada .items(). Ini adalah sama seperti idea sebelumnya untuk mengurangkan carian objek. Memanggil .items() menambah pertanyaan dan panggilan fungsi.

Buat nod DOM

Biasanya kita mungkin menggunakan rentetan untuk menulis HTML secara langsung untuk mencipta nod, tetapi sebenarnya melakukan ini

Kesahihan kod tidak boleh dijamin

Kecekapan operasi rentetan adalah rendah

Jadi anda harus menggunakan kaedah document.createElement() dan jika terdapat nod templat siap sedia dalam dokumen, anda harus menggunakan kaedah cloneNode() kerana selepas menggunakan kaedah createElement() anda perlu tetapkan atribut elemen beberapa kali, gunakan cloneNode() boleh mengurangkan bilangan tetapan atribut - begitu juga, jika anda perlu mencipta banyak elemen, anda harus menyediakan nod templat terlebih dahulu.


Pemasa

Jika anda menyasarkan kod yang sentiasa berjalan, anda tidak seharusnya menggunakan setTimeout, tetapi setInterval. setTimeout menetapkan semula pemasa setiap kali.


Lain-lain

Enjin skrip

Menurut ujian saya, kecekapan JScript Microsoft jauh lebih teruk daripada Spidermonkey Mozilla, baik dari segi kelajuan pelaksanaan dan pengurusan memori, kerana JScript pada dasarnya tidak dikemas kini sekarang. Tetapi SpiderMonkey tidak boleh menggunakan ActiveXObject


Pengoptimuman Fail

Pengoptimuman fail juga merupakan kaedah yang sangat berkesan Padamkan semua ruang dan ulasan dan letakkan kod ke dalam satu baris untuk mempercepatkan muat turun, bukan kelajuan penghuraian Ruang tidak menjejaskan tafsiran dan kelajuan pelaksanaan.

Ringkasan

Artikel ini meringkaskan beberapa kaedah yang saya temui dalam pengaturcaraan JavaScript untuk meningkatkan prestasi menjalankan JavaScript Malah, pengalaman ini berdasarkan beberapa prinsip:


Lebih pantas untuk hanya menggunakan apa yang tersedia Sebagai contoh, pembolehubah tempatan lebih pantas daripada pembolehubah global, pembolehubah langsung lebih pantas daripada membina objek pada masa jalan, dsb.


Kurangkan bilangan pelaksanaan sebanyak mungkin, seperti menyimpan cache yang memerlukan berbilang pertanyaan terlebih dahulu.


Gunakan ciri bahasa terbina dalam sebanyak mungkin, seperti pautan rentetan.


Gunakan API yang disediakan oleh sistem sebanyak mungkin, kerana API ini adalah kod binari yang disusun dan mempunyai kecekapan pelaksanaan yang tinggi


同时,一些基本的算法上的优化,同样可以用在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 < 7, 9;

最后我们来看一下空循环

代码10: 

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

代码11:

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

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

Kenyataan:
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn