Dalam bahasa pengaturcaraan biasa, parameter fungsi hanya boleh menjadi jenis asas atau rujukan objek, dan nilai pulangan hanya boleh menjadi jenis data asas atau rujukan objek. Tetapi dalam Javascript, fungsi adalah warga kelas pertama dan boleh diluluskan sebagai parameter atau dikembalikan sebagai nilai pulangan. Fungsi tertib tinggi yang dipanggil ialah fungsi yang boleh mengambil fungsi sebagai parameter atau fungsi sebagai nilai pulangan. Kedua-dua situasi ini mempunyai banyak senario aplikasi dalam pembangunan sebenar Artikel ini adalah ringkasan beberapa senario aplikasi yang saya temui dalam kerja dan pengajian.
Fungsi panggil balik
Penggunaan semula kod adalah salah satu kriteria penting untuk mengukur aplikasi. Dengan mengekstrak logik perniagaan yang diubah dan merangkumnya dalam fungsi panggil balik, kadar penggunaan semula kod boleh dipertingkatkan dengan berkesan. Sebagai contoh, kaedah forEach yang ditambahkan pada tatasusunan dalam ES5 merentasi tatasusunan dan memanggil fungsi yang sama pada setiap elemen.
array = {}; array.forEach = function(arr, fn){ for (var i = 0, len = arr.length; i < len; i++) { fn(arr[i], i, arr); } }
Fokuskan fokus perniagaan pada fungsi panggil balik tanpa perlu menulis kod traversal lagi setiap kali.
Fungsi separa
Sebagai aplikasi biasa untuk mengeluarkan fungsi sebagai nilai pulangan, ia adalah fungsi separa. Apa yang dipanggil fungsi separa merujuk kepada penggunaan mencipta fungsi yang memanggil bahagian-fungsi lain yang parameter atau pembolehubahnya telah dipratetap. Bagaimanapun, melihat definisi, saya tidak faham untuk apa perkara ini. Mari kita lihat contoh dahulu Contoh fungsi separa yang paling tipikal ialah pertimbangan jenis.
Objek JavaScript mempunyai tiga atribut: atribut prototaip, atribut kelas dan kebolehlanjutan. (Pelajar yang tidak tahu harus kembali dan membaca buku Rhino, halaman: 138) Atribut kelas ialah rentetan, yang tidak disediakan secara langsung dalam Javascript, tetapi kita boleh menggunakan Object.prototype.toString untuk mendapatkannya secara tidak langsung. Fungsi ini sentiasa mengembalikan bentuk berikut:
[Kelas objek]
Jadi kita boleh menulis satu siri fungsi isType.
Kod adalah seperti berikut:
isString = function(obj){ return Object.prototype.toString.call(obj) === "[object String]"; } isNumber = function(obj){ return Object.prototype.toString.call(obj) === "[object Number]"; } isArray = function(obj){ return Object.prototype.toString.call(obj) === "[object Array]"; }
Kebanyakan kod dalam fungsi ini diulang Pada masa ini, fungsi tertib tinggi membuat penampilan pertama yang cantik:
isType = function(type) { return function(obj) { return Object.prototype.toString.call(obj) === "[object " + type + "]"; } } isString = isType('String'); isNumber = isType('Number'); isArray = isType('Array');
Jadi bentuk mengembalikan fungsi tersuai baharu dengan menyatakan beberapa parameter ialah fungsi separa.
Karipap
Karipap juga dipanggil penilaian separa. Fungsi kari akan mula-mula menerima beberapa parameter Selepas menerima parameter ini, fungsi itu tidak akan menilai serta-merta, tetapi akan terus mengembalikan fungsi lain Parameter yang baru dimasukkan disimpan dalam penutupan yang dibentuk oleh fungsi. Apabila fungsi benar-benar dinilai, semua parameter yang diluluskan akan digunakan untuk penilaian sekaligus.
var currying = function(fn) { var args = []; return function() { if (arguments.length === 0) { return fn.applay(this, args); } else { args = args.concat(arguments); return arguments.callee; } } }
Andaikan kita mengambil pengiraan perbelanjaan harian selama sebulan sebagai contoh:
var currying = function(fn) { debugger; var args = []; return function() { if (arguments.length === 0) { return fn.apply(this, args); } else { Array.prototype.push.apply(args, arguments); return arguments.callee; } } } cost = function(){ var sum = 0; for (var i = 0, len = arguments.length; i < len; i++) { sum += arguments[i]; } return sum; } var cost = currying(cost); cost(100); cost(200); alert(cost())
Pendikitan acara
Dalam sesetengah senario, peristiwa tertentu mungkin dicetuskan berulang kali, tetapi fungsi pemprosesan acara tidak perlu dilaksanakan setiap kali. Sebagai contoh, pengiraan logik yang kompleks dilakukan dalam peristiwa tetingkap.ubah saiz Jika pengguna kerap menukar saiz penyemak imbas, pengiraan yang kompleks akan memberi kesan yang serius kepada prestasi kadangkala pengiraan logik ini tidak perlu dicetuskan setiap kali rezise berlaku dan hanya pengiraan terhad diperlukan beberapa kali. Pada masa ini kita perlu mengabaikan beberapa permintaan acara berdasarkan tempoh masa. Lihat fungsi pendikit berikut:
function throttle(fn, interval) { var doing = false; return function() { if (doing) { return; } doing = true; fn.apply(this, arguments); setTimeout(function() { doing = false; }, interval); } } window.onresize = throttle(function(){ console.log('execute'); }, 500);
Dengan mengawal masa pelaksanaan fungsi, anda boleh mencapai keseimbangan sempurna antara bilangan pelaksanaan fungsi dan keperluan fungsian. Peristiwa lain ialah mousemove. Jika kita mengikat acara ini pada elemen DOM, peristiwa itu akan dicetuskan berulang kali apabila tetikus bergerak ke atas elemen tersebut.
Acara sudah tamat
Untuk beberapa acara yang boleh dicetuskan dengan kerap, kadangkala kami ingin melakukan beberapa siri operasi selepas acara itu tamat. Pada masa ini kita boleh menggunakan fungsi tertib lebih tinggi untuk melakukan pemprosesan berikut:
function debounce(fn, interval) { var timer = null; function delay() { var target = this; var args = arguments; return setTimeout(function(){ fn.apply(target, args); }, interval); } return function() { if (timer) { clearTimeout(timer); } timer = delay.apply(this, arguments); } }; window.onresize = throttle(function(){ console.log('resize end'); }, 500);
Jika acara dicetuskan semasa proses ini, kosongkan pemegang acara terakhir dan ikat semula masa pelaksanaan.
Rujukan:
《Penjelasan mendalam tentang nod》
"Corak Reka Bentuk Javascript dan Amalan Pembangunan"