Mengapa melewatkan fungsi anonim besar sebagai argumen ke fungsi lain begitu banyak diterima dalam JavaScript?

27

Saya memiliki pendapat (yang saya yakin akan dibagikan oleh beberapa orang) bahwa melewati fungsi anonim yang berisi lebih dari beberapa baris kode, karena argumen ke fungsi lain mempengaruhi keterbacaan dan dokumentasi diri secara drastis, ke titik di mana saya merasa akan jauh lebih baik bagi siapa pun yang mungkin menggunakan kode untuk hanya mendeklarasikan fungsi bernama Atau setidaknya menetapkan fungsi anonim ke variabel sebelum mendeklarasikan fungsi utama

Namun, banyak pustaka JavaScript (jQuery, d3.js / NVD3.js) hanya untuk memberikan beberapa contoh, gunakan fungsi besar dengan cara ini.

Mengapa ini diterima secara luas dalam JavaScript? Apakah ini hal budaya, atau adakah keuntungan yang saya lewatkan, yang akan membuat penggunaan lebih disukai daripada mendeklarasikan fungsi yang disebutkan?

Adam Copley
sumber
1
Mungkin banyak hubungannya dengan menggunakan penutupan . Mungkin juga ada hubungannya dengan tidak ingin mengekspos fungsi aktual ke dunia luar (itulah sebabnya itu anonim).
Robert Harvey
3
@RobertHarvey Dengan kata lain, ini solusi untuk JavaScript yang tidak memiliki publik dan pribadi ?
Mason Wheeler
2
Di banyak tempat, fungsi anonim yang besar lebih mirip blok dan biasanya terasa cukup baik setelah Anda terbiasa. Aturan pelingkupan bahkan mendukung nuansa blok.
5
@MasonWheeler: Itu tergantung pada perspektif Anda. Seorang programmer Skema atau ECMAScript mungkin mengatakan itu publicdan privatesedang mencari solusi untuk tidak memiliki penutupan yang tepat.
Jörg W Mittag
1
@ JörgWMittag Hooray untuk Racket, sponsor bahasa resmi XKCD 927!
Mason Wheeler

Jawaban:

23

Tiga alasan utama yang dapat saya pikirkan:

  1. Akses Lingkup Induk
  2. Pribadi
  3. Pengurangan nama yang didefinisikan dalam cakupan yang lebih tinggi

Akses Lingkup Orangtua: Definisi fungsi sebaris memungkinkan kode sebaris untuk memiliki akses ke variabel yang ditentukan dalam cakupan induk. Ini bisa sangat berguna untuk banyak hal dan dapat mengurangi jumlah atau kompleksitas kode jika dilakukan dengan benar.

Jika Anda meletakkan kode dalam fungsi yang ditentukan di luar lingkup ini dan kemudian memanggil kode, Anda harus melewati status induk apa pun yang ingin diakses oleh fungsi tersebut.

Privasi: Kode di dalam definisi anonim sebaris lebih pribadi dan tidak dapat dipanggil oleh kode lain.

Pengurangan nama yang didefinisikan dalam cakupan yang lebih tinggi: Ini yang paling penting saat beroperasi dalam lingkup global, tetapi deklarasi anonim inline tetap tidak harus mendefinisikan simbol baru dalam cakupan saat ini. Karena Javascript tidak mensyaratkan penggunaan namespace secara alami, adalah bijaksana untuk menghindari mendefinisikan simbol yang lebih global daripada yang dibutuhkan secara minimal.


Editorial: Tampaknya menjadi hal budaya dalam Javascript di mana mendeklarasikan sesuatu secara anonim dianggap "lebih baik" daripada mendefinisikan fungsi dan menyebutnya bahkan ketika akses ruang lingkup orang tua tidak digunakan. Saya menduga ini awalnya karena masalah polusi namespace global di Javascript, kemudian mungkin karena masalah privasi. Tetapi sekarang telah berubah menjadi sesuatu yang bersifat budaya dan Anda dapat melihatnya diekspresikan dalam banyak kode publik (seperti yang Anda sebutkan).

Dalam bahasa seperti C ++, sebagian besar mungkin akan menganggapnya sebagai praktik yang kurang ideal untuk memiliki satu fungsi raksasa yang meluas di banyak halaman / layar. Tentu saja, C ++ memiliki namespacing bawaan, tidak menyediakan akses ruang lingkup orang tua dan memiliki fitur privasi sehingga dapat dimotivasi sepenuhnya oleh keterbacaan / pemeliharaan, sedangkan Javascript harus menggunakan ekspresi kode untuk mencapai privasi dan akses ruang lingkup orang tua. Jadi, JS tampaknya hanya termotivasi ke arah yang berbeda dan itu menjadi hal yang agak budaya dalam bahasa, bahkan ketika hal-hal yang memotivasi arah itu tidak diperlukan dalam kasus tertentu.

pacar00
sumber
Sebagai pengembang C ++ baru-baru ini pindah ke JS untuk banyak pekerjaan saya, jawaban ini sangat masuk akal, terutama titik 'akses ruang lingkup orang tua' - itu benar-benar memiliki kekuatan untuk sangat menyederhanakan kode Anda. Satu nitpick - C ++ memang memberikan akses lingkup induk di C ++ 11 lambdas :) Pasti +1.
Commander Coriander Salamander
8

Fungsi anonim digunakan untuk lebih banyak tujuan dalam JavaScript daripada di kebanyakan bahasa.

Pertama, mereka digunakan untuk penempatan nama dan memblokir pelingkupan. Sampai saat ini JavaScript tidak memiliki modul atau mekanisme penempatan nama apa pun lainnya yang menyebabkan penggunaan fungsi anonim untuk menyediakan fungsionalitas itu melalui Pola Modul. Sama sekali tidak ada manfaatnya dalam memberi nama fungsi-fungsi ini. Pada skala yang lebih kecil, karena kurangnya JavaScript untuk pelingkupan blok hingga saat ini, pola yang sama digunakan untuk meniru pelingkupan blok; terutama di tubuh loop. Menggunakan fungsi bernama dalam kasus ini akan secara aktif membingungkan.

Kedua, dan kurang spesifik JavaScript, fungsi anonim sering digunakan dengan fungsi urutan yang lebih tinggi yang meniru struktur kontrol. Misalnya, eachmetode jQuery . Saya ragu Anda mengabstraksikan setiap loop body atau if-branch menjadi sebuah fungsi setiap kali panjangnya lebih dari beberapa baris. Logika yang sama berlaku dalam kasus ini.

Alasan terakhir adalah pemrograman berbasis peristiwa adalah umum dalam JavaScript yang cenderung mengarah pada kode gaya kelanjutan-kelanjutan yang tidak disengaja . Anda membuat panggilan AJAX dan mendaftarkan panggilan balik yang, ketika dieksekusi, akan membuat panggilan AJAX lain dan mendaftarkan panggilan balik dll. Jika panggilan itu sinkron daripada asinkron, ini hanya akan menjadi urutan garis lurus kode dalam satu lingkup leksikal tunggal . Sekali lagi, saya ragu Anda akan abstrak setiap beberapa baris kode garis lurus menjadi suatu fungsi.

Ada juga faktor budaya dan, untuk alasan di atas antara lain, fungsi anonim jauh lebih umum dalam JavaScript daripada banyak bahasa lain dan digunakan lebih nyaman / longgar daripada banyak bahasa lain.

Derek Elkins
sumber
Struktur saya sendiri, mungkin naif dalam pengkodean C ++ kadang-kadang mengambil prinsip pengkodean berbasis peristiwa dan panggilan balik dari JavaScript melalui std :: function dan lambdas. Dalam kasus saya, ini sebagian karena saya sedang melakukan kode UI di C ++ dan tidak ingin melakukan operasi pemblokiran. Saya ingin tahu apakah praktik JavaScript hanya bermanfaat bagi siapa saja asalkan bahasa mendukungnya dengan baik.
Katana314