Fungsi tanda panah JavaScript: mengapa diperlukan, cara menanganinya, kapan menggunakannya, dan kapan tidak

Salah satu inovasi paling penting dari JavaScript modern adalah penampilan fungsi panah, yang kadang-kadang disebut fungsi panah "gemuk". Ketika mendeklarasikan fungsi tersebut, mereka menggunakan kombinasi karakter khusus - => .

Fungsi panah memiliki dua keunggulan utama dibandingkan fungsi tradisional. Yang pertama adalah sintaks yang sangat nyaman dan kompak. Yang kedua adalah bahwa pendekatan untuk bekerja dengan this dalam fungsi panah terlihat lebih intuitif daripada fungsi biasa.

gambar

Kadang-kadang ini dan keuntungan lainnya mengarah pada fakta bahwa sintaks panah diberikan preferensi tanpa syarat daripada cara lain untuk mendeklarasikan fungsi. Misalnya, konfigurasi eslint populer dari pasukan Airbnb yang setiap kali fungsi anonim dibuat, fungsi seperti itu akan seperti panah.

Namun, seperti konsep dan mekanisme lain yang digunakan dalam pemrograman, fungsi panah memiliki kelebihan dan kelemahannya. Penggunaannya dapat menyebabkan efek samping negatif. Untuk menggunakan fungsi panah dengan benar, Anda perlu tahu tentang kemungkinan masalah yang terkait dengannya.

Materi, terjemahan yang kami terbitkan hari ini, akan fokus pada bagaimana fungsi panah bekerja. Di sini kita akan mempertimbangkan situasi di mana penggunaannya dapat meningkatkan kode, dan situasi di mana mereka tidak boleh digunakan.

Fitur fungsi panah dalam JavaScript


Fungsi panah dalam JavaScript adalah sesuatu seperti fungsi lambda di Python dan blok di Ruby.

Ini adalah fungsi anonim dengan sintaks khusus yang mengambil sejumlah argumen dan bekerja dalam konteks ruang lingkup yang memasukkannya, yaitu, dalam konteks fungsi atau kode lain di mana mereka dideklarasikan.

Mari kita bicarakan ini secara lebih rinci.

▍ Fungsi panah sintaks


Fungsi panah dibangun sesuai dengan skema tunggal, sementara struktur fungsi dapat, dalam kasus khusus, disederhanakan. Struktur dasar dari fungsi panah terlihat seperti ini:

 (argument1, argument2, ... argumentN) => { //   } 

Daftar argumen fungsi adalah dalam tanda kurung, diikuti oleh panah yang terdiri dari = dan > karakter, dan kemudian muncul tubuh fungsi di kurung kurawal.

Ini sangat mirip dengan cara kerja fungsi biasa, perbedaan utamanya adalah bahwa kata kunci function dihilangkan di sini dan panah ditambahkan setelah daftar argumen.

Namun, dalam kasus tertentu, fungsi panah sederhana dapat dideklarasikan menggunakan konstruksi yang jauh lebih ringkas.

Pertimbangkan sintaks yang digunakan jika tubuh fungsi diwakili oleh satu ekspresi. Ini memungkinkan Anda melakukan tanpa kurung keriting yang membingkai tubuh fungsi, dan menghilangkan kebutuhan untuk secara eksplisit mengembalikan hasil evaluasi ekspresi, karena hasil ini akan dikembalikan secara otomatis. Misalnya, mungkin terlihat seperti ini:

 const add = (a, b) => a + b; 

Berikut ini varian lain dari notasi fungsi yang disingkat, yang digunakan ketika fungsi tersebut hanya memiliki satu argumen.

 const getFirst = array => array[0]; 

Seperti yang Anda lihat, tanda kurung di sekitar daftar argumen dihilangkan di sini. Selain itu, badan fungsi, yang dalam contoh ini diwakili oleh satu perintah, juga ditulis tanpa tanda kurung. Nanti kita akan berbicara lebih banyak tentang manfaat desain tersebut.

▍Kembalikan objek dan fungsi panah rekam pendek


Ketika bekerja dengan fungsi panah, beberapa konstruksi sintaks yang lebih kompleks juga digunakan, yang berguna untuk diperhatikan.

Misalnya, coba gunakan ekspresi garis tunggal untuk kembali dari fungsi literal objek. Tampaknya, mengingat apa yang sudah kita ketahui tentang fungsi panah, deklarasi fungsi akan terlihat seperti ini:

 (name, description) => {name: name, description: description}; 

Masalah dengan kode ini adalah ambiguitasnya. Yaitu, kurung kurawal yang ingin kita gunakan untuk menggambarkan objek tampak literal seperti kita mencoba untuk melampirkan tubuh fungsi di dalamnya.

Untuk menunjukkan ke sistem yang kami maksud objek literal, kita harus melampirkannya dalam tanda kurung:

 (name, description) => ({name: name, description: description}); 

▍ Fungsi panah dan konteks pelaksanaannya


Tidak seperti fungsi lainnya, fungsi panah tidak memiliki konteks eksekusi sendiri.

Dalam praktiknya, ini berarti bahwa mereka mewarisi entitas this dan arguments dari fungsi induk.

Misalnya, bandingkan dua fungsi yang disajikan dalam kode berikut. Salah satunya biasa, yang kedua adalah panah.

 const test = { name: 'test object', createAnonFunction: function() {   return function() {     console.log(this.name);     console.log(arguments);   }; }, createArrowFunction: function() {   return () => {     console.log(this.name);     console.log(arguments);   }; } }; 

Ada objek test dengan dua metode. Masing-masing dari mereka adalah fungsi yang membuat dan mengembalikan fungsi anonim. Perbedaan antara metode-metode ini adalah hanya di pertama mereka ekspresi fungsional tradisional digunakan, dan dalam fungsi panah kedua.

Jika kita bereksperimen dengan kode ini di konsol, meneruskan argumen yang sama ke metode objek, maka meskipun metode tersebut terlihat sangat mirip, kita akan mendapatkan hasil yang berbeda:

 > const anon = test.createAnonFunction('hello', 'world'); > const arrow = test.createArrowFunction('hello', 'world'); > anon(); undefined {} > arrow(); test object { '0': 'hello', '1': 'world' } 

Fungsi anonim memiliki konteksnya sendiri, jadi ketika dipanggil, saat Anda memanggil test.name , nilai properti name objek tidak akan test.name , dan saat Anda memanggil arguments , daftar argumen untuk fungsi yang digunakan untuk membuat dan mengembalikan fungsi yang sedang diselidiki tidak akan ditampilkan.

Dalam kasus fungsi panah, ternyata konteksnya bertepatan dengan konteks fungsi yang membuatnya, yang memberikan akses ke daftar argumen yang dilewati oleh fungsi ini dan properti name objek yang fungsi tersebut merupakan metode.

Situasi di mana fungsi panah meningkatkan kode


▍Mengolah daftar nilai


Fungsi lambda tradisional, serta fungsi panah, setelah muncul dalam JavaScript, biasanya digunakan dalam situasi di mana fungsi tertentu diterapkan ke setiap elemen daftar tertentu.

Misalnya, jika ada array nilai yang perlu dikonversi menggunakan metode array map , fungsi panah sangat ideal untuk menggambarkan konversi seperti itu:

 const words = ['hello', 'WORLD', 'Whatever']; const downcasedWords = words.map(word => word.toLowerCase()); 

Berikut adalah contoh yang sangat umum dari penggunaan fungsi panah yang serupa, yang terdiri dari bekerja dengan properti objek:

 const names = objects.map(object => object.name); 

Demikian pula, jika alih-alih tradisional for loop mereka menggunakan forEach loop modern berbasis iterator, maka fungsi panah menggunakan this entitas induk, membuat penggunaannya intuitif:

 this.examples.forEach(example => { this.runExample(example); }); 

▍ Janji dan rantai janji


Situasi lain di mana fungsi panah memungkinkan Anda untuk menulis kode yang lebih bersih dan lebih mudah dipahami diwakili oleh konstruksi perangkat lunak asinkron.

Jadi, janji sangat menyederhanakan pekerjaan dengan kode asinkron. Pada saat yang sama, bahkan jika Anda lebih suka menggunakan async / menunggu konstruksi, Anda tidak dapat melakukannya tanpa memahami janji-janji , karena konstruksi ini didasarkan pada mereka.

Namun, saat menggunakan janji, Anda harus mendeklarasikan fungsi yang dipanggil setelah penyelesaian kode asinkron atau penyelesaian panggilan asinkron ke API tertentu.

Ini adalah tempat yang ideal untuk menggunakan fungsi panah, terutama jika fungsi yang dihasilkan memiliki keadaan tertentu, mengacu pada sesuatu di objek. Misalnya, mungkin terlihat seperti ini:

 this.doSomethingAsync().then((result) => { this.storeResult(result); }); 

▍ Transformasi Objek


Kasus penggunaan umum lainnya untuk fungsi panah adalah untuk mengenkapsulasi transformasi objek.

Sebagai contoh, di Vue.js, ada pola umum untuk menyertakan fragmen penyimpanan Vuex secara langsung dalam komponen Vue menggunakan mapState .

Operasi ini mencakup deklarasi seperangkat "konverter" yang memilih dengan tepat apa yang diperlukan untuk komponen tertentu dari keadaan penuh awal.

Transformasi sederhana ini adalah tempat yang tepat untuk menggunakan fungsi panah. Sebagai contoh:

 export default { computed: {   ...mapState({     results: state => state.results,     users: state => state.users,   }); } } 

Situasi di mana fungsi panah tidak boleh digunakan


▍ Metode objek


Ada beberapa situasi di mana menggunakan fungsi panah bukan ide yang baik. Fungsi panah, jika digunakan dengan ringan, tidak hanya tidak membantu programmer, tetapi juga menjadi sumber masalah.

Situasi seperti pertama adalah menggunakan fungsi panah sebagai metode objek. Konteks eksekusi dan this , khusus untuk fungsi tradisional, adalah penting di sini.

Pada suatu waktu, itu populer untuk menggunakan kombinasi properti kelas dan fungsi panah untuk membuat metode dengan "penjilidan otomatis", yaitu yang dapat digunakan oleh penangan acara, tetapi tetap terikat pada kelas. Itu terlihat seperti ini:

 class Counter { counter = 0; handleClick = () => {   this.counter++; } } 

Menggunakan konstruksi yang serupa, bahkan jika fungsi handleClick dipanggil oleh event handler, dan tidak dalam konteks instance kelas Counter , fungsi ini memiliki akses ke data instance ini.

Namun, pendekatan ini memiliki banyak kekurangan dimana materi ini dikhususkan.

Meskipun penggunaan fungsi panah di sini, tentu saja, adalah cara yang mudah untuk mengikat fungsi, perilaku fungsi ini dalam banyak aspek jauh dari intuitif, mengganggu pengujian dan menciptakan masalah dalam situasi di mana, misalnya, mereka mencoba menggunakan objek yang sesuai sebagai prototipe.

Dalam kasus seperti itu, alih-alih fungsi panah, gunakan fungsi biasa, dan, jika perlu, ikat ke mereka contoh objek di konstruktor:

 class Counter { counter = 0; handleClick() {   this.counter++; } constructor() {   this.handleClick = this.handleClick.bind(this); } } 

▍Panggilan panjang


Fungsi panah dapat menjadi sumber masalah jika direncanakan untuk digunakan dalam banyak kombinasi berbeda, khususnya, dalam rangkaian panjang panggilan fungsi.

Alasan utama untuk masalah tersebut, seperti ketika menggunakan fungsi anonim, adalah bahwa mereka memberikan hasil jejak stack stack yang sangat tidak informatif.

Ini tidak terlalu buruk jika, misalnya, hanya ada satu tingkat fungsi panggilan bersarang, katakanlah, jika kita berbicara tentang fungsi yang digunakan dalam iterator. Namun, jika semua fungsi yang digunakan adalah fungsi tanda panah, dan fungsi-fungsi ini saling memanggil satu sama lain, maka jika terjadi kesalahan, tidak akan mudah untuk mengetahui apa yang terjadi. Pesan kesalahan akan terlihat seperti ini:

 {anonymous}() {anonymous}() {anonymous}() {anonymous}() {anonymous}() 

▍ Fungsi dengan konteks dinamis


Yang terakhir dari situasi yang kita bahas di mana fungsi panah dapat menjadi sumber masalah adalah menggunakannya di mana Anda membutuhkan dinamika pengikatan this .

Jika fungsi panah digunakan dalam situasi seperti itu, maka dinamika ikatan ini tidak akan berfungsi. Kejutan yang tidak menyenangkan ini dapat menyebabkan orang bingung tentang alasan apa yang terjadi pada mereka yang harus bekerja dengan kode di mana fungsi panah digunakan secara tidak benar.

Berikut adalah beberapa hal yang perlu diingat ketika mempertimbangkan menggunakan fungsi panah:

  • Penangan acara dipanggil dengan this terikat ke atribut event currentTarget .
  • Jika Anda masih menggunakan jQuery, pertimbangkan bahwa sebagian besar metode jQuery mengikat this ke elemen DOM yang dipilih.
  • Jika Anda menggunakan Vue.js, maka metode dan fungsi yang dihitung biasanya mengikat this ke komponen Vue.

Tentu saja, fungsi panah dapat digunakan dengan sengaja untuk mengubah perilaku standar mekanisme perangkat lunak. Tetapi, terutama dalam kasus dengan jQuery dan Vue, ini sering bertentangan dengan fungsi normal sistem, yang mengarah pada kenyataan bahwa programmer tidak dapat memahami mengapa beberapa kode yang terlihat sangat normal tiba-tiba menolak untuk bekerja.

Ringkasan


Fungsi panah adalah fitur JavaScript segar yang luar biasa. Mereka memungkinkan, dalam banyak situasi, menulis kode yang lebih nyaman daripada sebelumnya. Tetapi, seperti halnya dengan fitur-fitur lainnya, mereka memiliki kelebihan dan kekurangan. Oleh karena itu, Anda perlu menggunakan fungsi panah di mana mereka dapat berguna, tanpa menganggapnya sebagai pengganti lengkap untuk fungsi biasa.

Pembaca yang budiman! Pernahkah Anda mengalami situasi di mana penggunaan fungsi panah mengarah ke kesalahan, ketidaknyamanan, atau perilaku yang tidak terduga dari program?

Source: https://habr.com/ru/post/id428566/


All Articles