Akhir-akhir ini saya telah cukup lama bekerja dengan JavaScript, React dan Redux dan lebih khusus lagi saya telah mencoba melakukan beberapa pemrograman fungsional.

Salah satu hal yang menarik perhatian saya pada awalnya adalah bagaimana fungsi likefetch digunakan di dalam fungsi lain seolah-olah fungsi tersebut adalah bagian dari bahasa tersebut, seperti ini:

const getData = url => {
  fetch(url).then(...)
}

Sekarang, ini boleh saja sampai Anda ingin menguji getData saat offline, misalnya. Dalam dunia berorientasi objek, saya akan memasukkan dependensi saya melalui konstruktor saya, bagaimana saya bisa melakukan hal serupa secara fungsional?

Ada fitur bahasa fungsional yang menurut saya sangat sesuai dengan kebutuhan: kari.

Singkatnya, Currying berarti mengubah fungsi yang menggunakan N parameter menjadi fungsi yang menggunakan 1 parameter dalam satu waktu, sebanyak N kali:

sum(1,2)
curriedSum(1)(2)

Selain itu, ES2015 (spesifikasi JavaScript terbaru, Anda dapat mempelajarinya lebih lanjut di dokumentasi Babel) menawarkan kepada kita beberapa gula sintaksis untuk membuat fungsi kari:

const curriedSum = a => b => a + b
// equivalent to
const curriedSum = a => {
  return b => {
    return a + b
  }
}

Sekarang, kembali ke contoh awal, kita mungkin menulis

const getData = fetch => url => {
  fetch(url).then(...)
}
// at some point we initialize getData
startTheAppWhichKnowsTheUrl(getData(fetch))
// in your tests
const mockFetch = () => Promise.resolve(createMockedBody())
getData(mockFetch)(url) // will use the mocked response body

Apa yang kita lakukan di sini? Kami mendeklarasikan getData sebagai fungsi yang menerima satu parameter bernama fetch, dan mengembalikan fungsi lain yang menerima parameter lain, url.

Semakin saya menggunakan pola ini, semakin saya merasa berguna dalam semua situasi ini di mana kita tidak mengontrol tanda tangan yang diperlukan untuk fungsi yang kita teruskan, yang pada dasarnya bermuara pada hampir semua fungsi yang menerima panggilan balik dalam parameternya. . Misalnya: Array.map menerima panggilan balik yang memiliki nilai iterasi dan indeksnya sebagai parameter, dan mengembalikan nilai yang diubah; bagaimana jika kita ingin menentukan indeks tertentu yang akan diubah untuk panggilan balik kita? Kita dapat mencapainya dengan cara ini:

const zeroAtIndex = zeroIndex => (val, index) => {
  if (zeroIndex === index) {
    return 0
  }
  return val
}
[1,2,3].map(zeroAtIndex(2)) // [1,2,0]

Atau, jika Anda menggunakan React seperti yang saya lakukan akhir-akhir ini:

const onOnClick = (onItemSelected, item) => () => {
  onItemSelected(item)
}
const ItemView = ({onItemSelected, item}) => {
  return (
    <button onClick={onClick(onItemSelected, item)}>
      {item.title}
    <button>
  )
}

JavaScript berkembang cukup cepat dan dengan ES2015 mendapatkan beberapa sintaksis luar biasa yang dapat kita gunakan untuk menulis kode yang elegan dan mudah dipelihara. Ini benar-benar memasuki gaya penulisan kode saya sehari-hari dan menurut saya ini akan sangat berguna setiap kali saya mulai menulis beberapa kode fungsional murni.