Pemrograman fungsional telah membuat cukup banyak percikan di dunia pengembangan akhir-akhir ini. Dan untuk alasan yang baik: Teknik fungsional dapat membantumu menulis lebih banyak kode deklaratif yang lebih mudah dipahami sekilas, refaktor, dan tes. Show Salah satu pilar pemrograman fungsional adalah penggunaan khusus daftar dan operasi daftar. Dan hal-hal itu persis seperti apa terdengarnya: array dari berbagai hal, dan hal-hal yang kamu lakukan kepadanya. Tetapi pola pikir fungsional memperlakukannya sedikit berbeda dari yang kamu duga. Artikel ini akan melihat lebih dekat pada apa yang saya suka sebut operasi daftar "big three": Ini juga berarti kamu tidak perlu menulis perulangan
Ingin tahu? Mari kita selami. Peta Dari Daftar ke DaftarSeringkali, kita menemukan diri kita perlu mengambil array dan memodifikasi setiap elemen di dalamnya dengan cara yang persis sama. Contoh-contoh yang umum adalah mengkuadratkan setiap elemen dalam array angka, mengambil nama dari daftar pengguna, atau menjalankan regex pada suatu array string.
Ketika kamu memanggil Pada dasarnya,
Mari kita lihat beberapa kode. map dalam PrakteknyaMisalkan kita memiliki aplikasi yang mengelola berbagai tugasmu untuk hari itu. Setiap // Durations are in minutes var tasks = [ { 'name' : 'Write for Envato Tuts+', 'duration' : 120 }, { 'name' : 'Work out', 'duration' : 60 }, { 'name' : 'Procrastinate on Duolingo', 'duration' : 240 } ]; Katakanlah kita ingin membuat array baru hanya dengan nama setiap tugas, sehingga kita dapat melihat semua yang telah kita selesaikan hari ini. Dengan menggunakan perulangan var task_names = []; for (var i = 0, max = tasks.length; i < max; i += 1) { task_names.push(tasks[i].name); } JavaScript juga menawarkan perulangan var task_names = []; tasks.forEach(function (task) { task_names.push(task.name); }); Dengan menggunakan var task_names = tasks.map(function (task, index, array) { return task.name; }); Saya menyertakan parmeter Ada beberapa perbedaan penting antara dua pendekatan tersebut:
Menghasilkan, semua fungsi yang akan kita lihat hari ini pada bagian karakteristik tersebut. Fakta bahwa kita tidak harus mengelola keadaan perulangan secara manual membuat kode kita lebih sederhana dan lebih mudah dipelihara. Fakta bahwa kita dapat beroperasi secara langsung pada elemen daripada harus mengindeks ke dalam array membuat hal-hal lebih mudah dibaca. Menggunakan perulangan
Menjaga jumlah tempat di mana kamu mengubah keadaan ke minimum absolut adalah prinsip penting dari pemrograman fungsional. Itu membuat kode lebih aman dan lebih dimengerti. Sekarang juga saat yang tepat untuk menunjukkan bahwa jika kamu berada di Node, mengetes contoh ini di konsol browser Firefox, atau menggunakan Babel atau Traceur, kamu dapat menulis ini lebih singkat dengan fungsi panah ES6: var task_names = tasks.map((task) => task.name ); Fungsi panah membiarkan kita meninggalkan kata kunci Itu tidak jauh lebih mudah dibaca daripada itu. GotchaCallback yang kamu teruskan ke Jika kamu lupa, Untungnya, ini adalah satu-satunya gotcha dengan ImplementasiMembaca implementasi adalah bagian penting dari pemahaman. Jadi, mari tulis var map = function (array, callback) { var new_array = []; array.forEach(function (element, index, array) { new_array.push(callback(element)); }); return new_array; }; var task_names = map(tasks, function (task) { return task.name; }); Kode ini menerima array dan fungsi callback sebagai argumen. Ini kemudian membuat array baru;
menjalankan callback pada setiap elemen pada array yang kita teruskan; mendorong hasil ke dalam array baru; dan mengembalikan array baru. Jika kamu menjalankan ini di konsolmu, kamu akan mendapatkan hasil yang sama seperti sebelumnya. Pastikan kamu menginisialisasi Meskipun kkita menggunakan perulangan for pada dasarnya, membungkusnya ke dalam fungsi menyembunyikan detail dan memungkinkan kita bekerja dengan abstraksi sebagai gantinya. Itu membuat kode kita lebih bersifat deklaratif—ia mengatakan apa yang harus dilakukan, bukan bagaimana melakukannya. Kamu akan menghargai betapa kodemu ini dibuat lebih mudah dibaca, dipelihara, dan, erm, mudah di-debug. Menyaring KebisinganSelanjutnya dari operasi array kita adalah Seperti Juga seperti
filter dalam PrakteknyaMari kita lihat kembali contoh tugas kita. Daripada menarik nama setiap tugas, katakanlah saya ingin mendapatkan daftar tugas yang membutuhkan waktu dua jam atau lebih untuk menyelesaikannya. Dengan menggunakan var difficult_tasks = []; tasks.forEach(function (task) { if (task.duration >= 120) { difficult_tasks.push(task); } }); Dengan var difficult_tasks = tasks.filter(function (task) { return task.duration >= 120; }); // Using ES6 var difficult_tasks = tasks.filter((task) => task.duration >= 120 ); Di sini, saya telah melanjutkan dan meninggalkan argumen Sama seperti
GotchaCallback yang kamu berikan ke Jika kamu
lupa pernyataan return, callback-mu akan mengembalikan Jika kamu menuju ke rute lain, dan mengembalikan sesuatu yang tidak secara eksplisit Selalu pastikan callbackmu menyertakan pernyataan return eksplisit. Dan selalu pastikan callback-mu di ImplementasiSekali lagi, cara terbaik untuk memahami sepotong kode adalah ... yah, dengan menulisnya. Mari kita gulirkan var filter = function (array, callback) { var filtered_array = []; array.forEach(function (element, index, array) { if (callback(element, index, array)) { filtered_array.push(element); } }); return filtered_array; }; Mengurangi Array
Sama seperti
Perhatikan bahwa callback mendapat nilai sebelumnya pada setiap perulangan. Pada perulangan pertama, tidak ada nilai sebelumnya. Inilah sebabnya mengapa kamu memiliki pilihan untuk meneruskan Akhirnya, ingatlah bahwa reduce dalam PrakteknyaKarena Katakanlah kita ingin mencari jumlah daftar angka. Menggunakan perulangan, itu terlihat seperti ini: var numbers = [1, 2, 3, 4, 5], total = 0; numbers.forEach(function (number) { total += number; }); Meskipun ini bukan kasus penggunaan yang buruk untuk var total = [1, 2, 3, 4, 5].reduce(function (previous, current) { return previous + current; }, 0); Pertama, kita memanggil Jika kita selangkah demi selangkah, tampilannya seperti ini:
Jika kamu bukan penggemar tabel, jalankan cuplikan ini di konsol: var total = [1, 2, 3, 4, 5].reduce(function (previous, current, index) { var val = previous + current; console.log("The previous value is " + previous + "; the current value is " + current + ", and the current iteration is " + (index + 1)); return val; }, 0); console.log("The loop is done, and the final value is " + total + "."); Ringkasnya: Mari kita kembali ke contoh tugas kita. Kita telah mendapatkan daftar nama tugas dari Bagaimana jika kita ingin mengetahui jumlah total waktu yang kita habiskan bekerja hari ini? Menggunakan perulangan var total_time = 0; tasks.forEach(function (task) { // The plus sign just coerces // task.duration from a String to a Number total_time += (+task.duration); }); Dengan var total_time = tasks.reduce(function (previous, current) { return previous + current; }, 0); // Using arrow functions var total_time = tasks.reduce((previous, current) previous + current ); Mudah. Itu hampir seluruh yang ada untuk hal itu. Hampir, karena JavaScript
memberi kita satu metode yang lebih sedikit diketahui, yang disebut var array_of_arrays = [[1, 2], [3, 4], [5, 6]]; var concatenated = array_of_arrays.reduce( function (previous, current) { return previous.concat(current); }); console.log(concatenated); // [1, 2, 3, 4, 5, 6];
var array_of_arrays = [[1, 2], [3, 4], [5, 6]]; var concatenated = array_of_arrays.reduceRight( function (previous, current) { return previous.concat(current); }); console.log(concatenated); // [5, 6, 3, 4, 1, 2]; Saya menggunakan GotchaTiga gotcha besar dengan
Untungnya, dua yang pertama mudah dihindari. Memutuskan apa nilai awalmu harus bergantung pada apa yang kamu lakukan, tetapi kamu akan cepat menguasainya. Yang terakhir mungkin tampak agak aneh. Jika Ada beberapa alasan bagus untuk itu. Pertama, Kedua, jika ImplementasiSaatnya untuk tampilan terakhir kita pada dasarnya. Seperti biasa, Mozilla memiliki polyfill antipeluru untuk reduce jika kamu ingin memeriksanya. var reduce = function (array, callback, initial) { var accumulator = initial || 0; array.forEach(function (element) { accumulator = callback(accumulator, array[i]); }); return accumulator; }; Dua hal yang perlu diperhatikan di sini:
Menggunakannya bersamaan: Map, Filter, Reduce, dan ChainabilityPada titik ini, kamu mungkin tidak begitu terkesan. Cukup adil: Setelah semua, kekuatan sejati mereka terletak pada keterkaitan mereka. Katakanlah saya ingin melakukan hal berikut:
Pertama, mari tentukan tugas-tugas kita untuk hari Senin dan Selasa: var monday = [ { 'name' : 'Write a tutorial', 'duration' : 180 }, { 'name' : 'Some web development', 'duration' : 120 } ]; var tuesday = [ { 'name' : 'Keep writing that tutorial', 'duration' : 240 }, { 'name' : 'Some more web development', 'duration' : 180 }, { 'name' : 'A whole lot of nothing', 'duration' : 240 } ]; var tasks = [monday, tuesday]; Dan sekarang, transformasi kita yang indah: var result = tasks.reduce(function (accumulator, current) { return accumulator.concat(current); }).map(function (task) { return (task.duration / 60); }).filter(function (duration) { return duration >= 2; }).map(function (duration) { return duration * 25; }).reduce(function (accumulator, current) { return [(+accumulator) + (+current)]; }).map(function (dollar_amount) { return '$' + dollar_amount.toFixed(2); }).reduce(function (formatted_dollar_amount) { return formatted_dollar_amount; }); Atau, lebih ringkas: // Concatenate our 2D array into a single list var result = tasks.reduce((acc, current) => acc.concat(current)) // Extract the task duration, and convert minutes to hours .map((task) => task.duration / 60) // Filter out any task that took less than two hours .filter((duration) => duration >= 2) // Multiply each tasks' duration by our hourly rate .map((duration) => duration * 25) // Combine the sums into a single dollar amount .reduce((acc, current) => [(+acc) + (+current)]) // Convert to a "pretty-printed" dollar amount .map((amount) => '$' + amount.toFixed(2)) // Pull out the only element of the array we got from map .reduce((formatted_amount) =>formatted_amount); Jika kamu sudah sampai sejauh ini, ini seharusnya cukup mudah. Ada dua sedikit keanehan yang bisa dijelaskan. Pertama, pada baris 10, saya seharusnya menulis: // Remainder omitted reduce(function (accumulator, current) { return [(+accumulator) + (+current_]; }) Dua hal yang perlu dijelaskan di sini:
Bit kedua yang mungkin membuatmu sedikit tidak nyaman adalah // Remainder omitted map(function (dollar_amount) { return '$' + dollar_amount.toFixed(2); }).reduce(function (formatted_dollar_amount) { return formatted_dollar_amount; }); Itu memanggil Cara lain untuk melakukan ini adalah dengan menghapus panggilan untuk mengurangi, dan mengindeks ke dalam array yang memuntahkan var result = tasks.reduce(function (accumulator, current) { return accumulator.concat(current); }).map(function (task) { return (task.duration / 60); }).filter(function (duration) { return duration >= 2; }).map(function (duration) { return duration * 25; }).reduce(function (accumulator, current) { return [(+accumulator) + (+current)]; }).map(function (dollar_amount) { return '$' + dollar_amount.toFixed(2); })[0]; Itu sangat benar. Jika kamu lebih nyaman menggunakan indeks array, silakan saja. Tetapi saya mendorongmu untuk tidak melakukannya. Salah satu cara paling ampuh untuk menggunakan fungsi-fungsi ini adalah dalam bidang pemrograman reaktif, di mana kamu tidak akan bebas menggunakan indeks array. Menendang kebiasaan itu sekarang akan membuat teknik belajar reaktif jauh lebih mudah dalam keseluruhannya. Akhirnya, mari kita lihat bagaimana teman kita perulangan var concatenated = monday.concat(tuesday), fees = [], formatted_sum, hourly_rate = 25, total_fee = 0; concatenated.forEach(function (task) { var duration = task.duration / 60; if (duration >= 2) { fees.push(duration * hourly_rate); } }); fees.forEach(function (fee) { total_fee += fee }); var formatted_sum = '$' + total_fee.toFixed(2); Ditoleransi, tetapi ramai. Kesimpulan & Langkah BerikutnyaPada tutorial ini, kamu telah belajar bagaimana Sekarang, saya yakin kamu ingin berlatih dan membaca lebih lanjut. Berikut adalah tiga saran utama saya untuk ke mana harus menuju selanjutnya:
JavaScript telah menjadi salah satu bahasa de-facto yang bekerja di web. Bukan
tanpa alur pembelajaran, dan ada banyak framework dan library untuk membuatmu sibuk juga. Jika kamu mencari sumber daya tambahan untuk dipelajari atau digunakan dalam pekerjaanmu, periksa apa yang kami miliki di Envato marketplace. Jika kamu ingin lebih banyak tentang hal semacam ini, cek profil saya dari waktu ke waktu; tangkap saya di Twitter (@PelekeS); atau klik blog saya di http://peleke.me. Pertanyaan, komentar, atau kebingungan? Biarkan mereka di bawah, dan saya akan melakukan yang terbaik untuk kembali ke masing-masing secara individual. |