Rekomendasi terkait: tutorial javascript
apply(context,[arguments])
, call(context,param1,param2,...)
.Currying adalah teknik yang mengubah fungsi yang menerima beberapa parameter menjadi fungsi yang menerima satu parameter (parameter pertama dari fungsi asli), dan mengembalikan fungsi baru yang menerima parameter tersisa dan mengembalikan hasilnya.
Misalnya, berikut adalah fungsi add()
, yaitu fungsi yang digunakan untuk memproses penambahan dan penjumlahan parameter (param1, params2,...) yang kita teruskan ke dalamnya.
// Ini adalah fungsi `add(x, y)` pertama dengan dua parameter `x`, `y` fungsi add(x, y){ kembalikan x + y; } // Panggil fungsi `add()` dan berikan dua parameter `4` dan `6` tambahkan(4,6); // Simulasikan pengoperasian komputer, teruskan parameter pertama 4 pada langkah pertama fungsi tambah(4, y){ kembalikan 4 + kamu; } // Simulasikan pengoperasian komputer, teruskan parameter pertama 6 pada langkah kedua fungsi tambah(4, 6){ kembali 4 + 6; }
Bagaimana jadinya jika kita menggunakan fungsi add()
? Berikut implementasi sederhananya:
// Fungsi kari add() dapat menerima beberapa parameter function add(x,y){ if (ketik y === 'tidak terdefinisi') { fungsi pengembalian (baru){ kembalikan x + baru; } } // Aplikasi lengkap mengembalikan x + y; } // Tes panggilan console.log(typeof add(4)); // [Fungsi] konsol.log(tambahkan(4)(6)); // 10 // Anda dapat membuat fungsi simpan let saveAdd = add(4); console.log(saveAdd(6)); // 10
Seperti yang dapat dilihat dari fungsi kari add()
sederhana di atas, fungsi tersebut dapat menerima beberapa fungsi dan kemudian mengembalikan fungsi baru untuk melanjutkan memproses fungsi yang tersisa.
Di sini kita membuat fungsi kari publik, sehingga kita tidak perlu mengimplementasikan proses kari yang rumit di dalamnya setiap kali kita menulis sebuah fungsi.
//Definisikan fungsi createCurry fungsi createCurry(fn){ var irisan = Array.prototipe.irisan, disimpan_args = irisan.panggilan(argumen,1); fungsi kembali () { biarkan new_args = irisan.panggilan(argumen), args = disimpan_args.concat(args_baru); kembali fn.apply(null,args); }}
Dalam fungsi kari publik di atas:
arguments
bukanlah array nyata, tetapi sebuah objek dengan atribut length
, jadi kami meminjam metode slice
dari Array.prototype
untuk membantu kami mengubah arguments
menjadi array nyata, Untuk memfasilitasi operasi kami yang lebih baik.createCurry
untuk pertama kalinya, stored_args
menampung parameter kecuali parameter pertama, karena parameter pertama adalah fungsi yang perlu kita kari.createCurry
, variabel new_args
mendapatkan parameter dan mengubahnya menjadi array.stored_args
melalui penutupan dan menggabungkan nilai variabel new_args
ke dalam array baru dan menugaskannya ke variabel args
.fn.apply(null,args)
dipanggil untuk menjalankan fungsi kari.Sekarang mari kita uji fungsi kari publik
// fungsi biasa add() fungsi tambah(x, y){ kembalikan x + y; } // Curry untuk mendapatkan fungsi baru var newAdd = createCurry(add,4); konsol.log(tambahan baru(6)); // 10 //Cara sederhana lainnya console.log(createCurry(add,4)(6));// 10
Tentu saja, ini tidak terbatas pada penggabungan dua parameter, tetapi juga beberapa parameter:
// Beberapa parameter Fungsi biasa fungsi tambah (a,b,c,d){ kembalikan a + b + c + d; } // Curry fungsi untuk mendapatkan fungsi baru, beberapa parameter dapat dibagi sesuka hati console.log(createCurry(add,4,5)(5,6)); // 20 // Kari dua langkah let add_one = createCurry(add,5); konsol.log(add_one(5,5,5));// 20 biarkan add_two = buatCurry(add_one,4,6); console.log(add_two(6)); // 21Melalui
contoh di atas, kita dapat menemukan batasannya, yaitu apakah itu dua parameter atau beberapa parameter, hanya dapat dieksekusi dalam dua langkah, seperti rumus berikut:
jika kita ingin lebih fleksibel:
;
Setelah latihan di atas, kami menemukan bahwa fungsi kari yang kami buat memiliki batasan tertentu. Kami berharap fungsi tersebut dapat dijalankan dalam beberapa langkah:
// Membuat fungsi kari yang dapat dijalankan dalam beberapa langkah Fungsi , jalankan ketika jumlah parameter terpenuhi: // Rumus fungsi: fn(x,y,z,w) ==> fn(x)(y)(z)(w); biarkan createCurry = (fn,...params)=> { biarkan args = parsm ||. let fnLen = fn.length; // Tentukan panjang parameter fungsi kari kembali (...res)=> { // Dapatkan semua parameter sebelumnya melalui rantai cakupan let allArgs = args.slice(0); // Salin secara mendalam parameter args yang dibagikan oleh penutupan untuk menghindari dampak operasi selanjutnya (tipe referensi) allArgs.push(...res); if(allArgs.panjang < fnLen){ // Ketika jumlah parameter kurang dari panjang parameter fungsi asli, panggil fungsi createCurry secara rekursif return createCurry.call(this,fn,...allArgs); }kalau tidak{ // Ketika jumlah parameter terpenuhi, eksekusi fungsi pemicu kembali fn.apply(this,allArgs); } } } // Fungsi biasa fungsi add(a,b,c,d){ dengan beberapa parameter kembalikan a + b + c + d; } //Uji fungsi kari let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); //
Kami telah menerapkan fungsi kari yang fleksibel selama lebih dari 10 tahun, tetapi di sini kami menemukan masalah lain:
curryAdd(add,1,2,3,4)()
;add()
yang asli. Ini juga merupakan salah satu cara; tetapi karena kami memenuhi jumlah parameter di sini, kami masih menangani situasi ini.Di sini kita hanya perlu membuat penilaian sebelum mengembalikan fungsinya:
let createCurry = (fn,...params)=> { biarkan args = parsm ||. let fnLen = fn.length; // Tentukan panjang parameter fungsi kari if(panjang === _args.panjang){ //Tambahkan penilaian. Jika jumlah parameter untuk pertama kalinya cukup, panggil fungsi secara langsung untuk mendapatkan hasilnya return fn.apply(this,args); } kembali (...res)=> { biarkan allArgs = args.slice(0); allArgs.push(...res); if(allArgs.panjang < fnLen){ kembalikan createCurry.call(ini,fn,...allArgs); }kalau tidak{ return fn.apply(ini,semuaArgs); } }}
Di atas dapat dianggap sebagai fungsi kari yang fleksibel, tetapi di sini tidak terlalu fleksibel karena kita tidak dapat mengontrol kapan dijalankan, selama jumlah parameter mencukupi, maka akan dijalankan secara otomatis. Apa yang harus kita lakukan jika kita ingin mencapai waktu yang dapat mengontrol pelaksanaannya?
Mari kita jelaskan rumus fungsinya di sini:
// Jika parameter sudah terpenuhi, panggil fungsi let createCurry = (fn,...params)=> { biarkan args = parsm ||. let fnLen = fn.length; // Tentukan panjang parameter fungsi kari //Tentu saja penilaian di sini perlu dikomentari, jika tidak, hasilnya akan langsung dieksekusi ketika jumlah parameter mencukupi untuk pertama kalinya //if(length === _args.length){ // Tambahkan penilaian. Jika jumlah parameter untuk pertama kalinya cukup, panggil fungsi secara langsung untuk mendapatkan hasilnya //return fn.apply(this,args); //} kembali (...res)=> { biarkan allArgs = args.slice(0); allArgs.push(...res); // Di sini dinilai apakah parameter masukan lebih besar dari 0. Jika lebih besar dari 0, dinilai apakah jumlah parameter mencukupi. // && tidak dapat digunakan di sini. Jika && digunakan, hasilnya akan dieksekusi ketika jumlah parameter mencukupi. if(res.length > 0 || allArgs.length < fnLen){ kembalikan createCurry.call(ini,fn,...allArgs); }kalau tidak{ return fn.apply(ini,semuaArgs); } } } // Fungsi biasa fungsi add(a,b,c,d){ dengan beberapa parameter kembalikan a + b + c + d; } // Uji fungsi kari yang dapat dikontrol let curryAdd = createCurry(add,1); console.log(curryAdd(2)(3)(4)); // fungsi konsol.log(curryAdd(2)(3)(4)()); // 10 console.log(curryAdd(2)(3)()); // Mengembalikan NaN ketika parameternya tidak mencukupi.
Rekomendasi terkait: Tutorial pembelajaran JavaScript.
Di atas adalah untuk membicarakan detail fungsi JavaScript. harap perhatikan php Artikel terkait lainnya di situs web Cina!