Menggunakan variabel _ (garis bawah) dengan fungsi panah di ES6 / Typecript

120

Saya menemukan konstruksi ini dalam contoh Angular dan saya bertanya-tanya mengapa ini dipilih:

_ => console.log('Not using any parameters');

Saya memahami bahwa variabel _ berarti tidak peduli / tidak digunakan tetapi karena ini adalah satu-satunya variabel, adakah alasan untuk lebih memilih penggunaan _ daripada:

() => console.log('Not using any parameters');

Tentunya ini tidak boleh kurang dari satu karakter untuk diketik. Sintaks () menyampaikan maksud dengan lebih baik menurut saya dan juga lebih spesifik jenisnya karena jika tidak, menurut saya contoh pertama seharusnya terlihat seperti ini:

(_: any) => console.log('Not using any parameters');

Jika penting, ini adalah konteks di mana itu digunakan:

submit(query: string): void {
    this.router.navigate(['search'], { queryParams: { query: query } })
      .then(_ => this.search());
}
Berhenti
sumber
1
Bagaimana Anda bisa mengkhawatirkan ketikan atau jenis kekhususan untuk parameter yang tidak pernah digunakan?
3
Saya adalah pengembang C ++ berdasarkan perdagangan jadi saya rasa saya selalu khawatir tentang kekhususan jenis :-).
Hentikan
6
Secara pribadi, pola _ => mengurangi jumlah tanda kurung sehingga lebih mudah dibaca: doStuff (). Then (() => action ()) vs doStuff (). Then (_ => action ()).
Damien Golding

Jawaban:

94

Alasan mengapa gaya ini dapat digunakan (dan mungkin mengapa gaya ini digunakan di sini) adalah karena _satu karakter lebih pendek dari ().

Tanda kurung opsional termasuk dalam masalah gaya yang sama seperti tanda kurung kurawal opsional . Ini adalah masalah selera dan gaya kode untuk sebagian besar, tetapi verbositas disukai di sini karena konsistensi.

Sementara fungsi panah memungkinkan satu parameter tanpa tanda kurung, itu tidak konsisten dengan nol, satu dirusak, satu istirahat dan beberapa parameter:

let zeroParamFn = () => { ... };
let oneParamFn = param1 => { ... };
let oneParamDestructuredArrFn = ([param1]) => { ... };
let oneParamDestructuredObjFn = ({ param1 }) => { ... };
let twoParamsFn = (param1, param2) => { ... };
let restParamsFn = (...params) => { ... };

Meskipun is declared but never usedkesalahan telah diperbaiki di TypeScript 2.0 untuk parameter yang digarisbawahi, _juga dapat memicu unused variable/parameterperingatan dari linter atau IDE. Ini adalah argumen yang cukup kuat untuk tidak melakukan ini.

_dapat digunakan secara konvensional untuk parameter yang diabaikan (seperti jawaban lain yang sudah dijelaskan). Meskipun ini mungkin dianggap dapat diterima, kebiasaan ini dapat mengakibatkan konflik dengan _ruang nama Underscore / Lodash, juga terlihat membingungkan ketika ada beberapa parameter yang diabaikan. Untuk alasan ini, bermanfaat untuk memiliki parameter yang digarisbawahi dengan nama yang benar (didukung di TS 2.0), juga menghemat waktu untuk mencari tahu tanda tangan fungsi dan mengapa parameter ditandai sebagai diabaikan (ini menentang tujuan _parameter sebagai pintasan):

let fn = (param1, _unusedParam2, param3) => { ... };

Untuk alasan yang tercantum di atas, saya pribadi akan menganggap _ => { ... }gaya kode nada buruk yang harus dihindari.

Estus Flask
sumber
1
Ini satu karakter lebih pendek tetapi jumlah penekanan tombolnya sama untuk kebanyakan IDE, karena menekan tombol (biasanya disertai dengan ). Saya pribadi lebih suka menggunakan pparameter, saya juga bertanya-tanya apakah ini memiliki masalah kinerja
Mojimi
69

The ()sintaks menyampaikan imho lebih baik maksud dan juga lebih jenis tertentu

Tidak persis. ()mengatakan bahwa fungsi tersebut tidak mengharapkan argumen apa pun, tidak mendeklarasikan parameter apa pun. Fungsinya .lengthadalah 0.

Jika Anda menggunakan _, ini secara eksplisit menyatakan bahwa fungsi tersebut akan diteruskan satu argumen, tetapi Anda tidak peduli tentang itu. Fungsinya .lengthakan menjadi 1, yang mungkin penting dalam beberapa framework.

Jadi dari perspektif tipe, ini mungkin hal yang lebih akurat untuk dilakukan (terutama ketika Anda tidak mengetiknya dengan anybut, katakanlah, _: Event). Dan seperti yang Anda katakan, itu satu karakter yang kurang untuk diketik yang juga lebih mudah dijangkau pada beberapa keyboard.

Bergi
sumber
6
Pikiran pertama saya adalah bahwa _ membuatnya hanya jelas dengan konvensi bahwa tidak ada argumen yang perlu dipertimbangkan ketika mencoba memahami fungsinya. Menggunakan () membuatnya eksplisit, tidak perlu memindai kode untuk kemungkinan penggunaan _ (yang akan melanggar konvensi). Tetapi Anda membuka mata saya untuk juga mempertimbangkan nilai dari mendokumentasikan bahwa ada nilai yang diteruskan ke fungsi tersebut, yang jika tidak, tidak selalu jelas.
Hentikan
Saya baru menyadari kode saya penuh dengan _variabel fungsi panah yang tidak digunakan , saya ingin tahu apakah ada perbedaan kinerja dibandingkan dengan menggunakan()
Mojimi
25

Saya kira _ =>ini baru saja digunakan () =>karena _umum dalam bahasa lain di mana tidak diizinkan untuk hanya menghilangkan parameter seperti di JS.

_ populer di Go dan juga digunakan di Dart untuk menunjukkan bahwa parameter diabaikan dan mungkin parameter lain yang tidak saya ketahui.

Günter Zöchbauer
sumber
4
Python juga mengikuti konvensi ini, saya kira.
Jaime RGP
7
Penggunaan _ini mungkin dipinjam dari bahasa fungsional seperti ML dan Haskell, yang lama mendahului penemuan Python (apalagi Go, Dart, atau TypeScript).
ruakh
1
Ruby juga melakukannya ( po-ru.com/diary/rubys-magic-underscore ) dan F # juga (dan bahasa lain yang dipengaruhi oleh keluarga ML)
Mariusz Pawelski
Scala menyukai garis bawah ( termasukelp.com/scala/use-of-underscore-in-scala.aspx ). Bahasa mana lagi yang mengikuti apa yang dilakukan Scala dengan tipe anonim dengan garis bawah.
Sam
Saya kira Scala juga mengambilnya dari beberapa bahasa lain. Hampir tidak ada bahasa pemrograman yang belum ada di tahun 70-an: D Kebanyakan hanya cara-cara baru untuk menggabungkan hal-hal tersebut.
Günter Zöchbauer
11

Dimungkinkan untuk membedakan antara kedua penggunaan, dan beberapa framework menggunakan ini untuk mewakili berbagai jenis callback. Misalnya saya pikir kerangka kerja node express menggunakan ini untuk membedakan antara jenis middleware, misalnya penangan kesalahan menggunakan tiga argumen, sedangkan perutean menggunakan dua.

Diferensiasi tersebut dapat terlihat seperti contoh di bawah ini:

const f1 = () => { } // A function taking no arguments
const f2 = _ => { }  // A function with one argument that doesn't use it

function h(ff) { 
  if (ff.length === 0) {
    console.log("No argument function - calling directly");
    ff();
  } else if (ff.length === 1) {
    console.log("Single argument function - calling with 1");
    ff(1);
  }
}

h(f1);
h(f2);

Michael Anderson
sumber
1
Ini didasarkan pada jawaban Bergi, tetapi saya pikir menambahkan contoh sedikit lebih banyak mengedit daripada yang saya senang lakukan pada posting orang lain.
Michael Anderson
0

Ketika saya menulis posting, saya mendapat kesan _bahwa satu-satunya cara untuk membuat fungsi panah tanpa (), yang membuat saya percaya bahwa penggunaan _dapat memiliki beberapa keuntungan kecil, tetapi saya salah. @Halt telah mengonfirmasi di komentar bahwa ia berperilaku seperti variabel lain, ini bukan konstruksi bahasa khusus.


Saya ingin menyebutkan satu hal lagi yang saya sadari tentang fungsi panah garis bawah ini saat menguji diri saya sendiri yang tidak saya temukan disebutkan di mana pun. Anda dapat menggunakan garis bawah dalam fungsi sebagai parameter , meskipun ini mungkin bukan penggunaan yang dimaksudkan karena seharusnya mewakili parameter yang tidak digunakan. Untuk kejelasan, saya tidak akan benar-benar merekomendasikan menggunakannya dengan cara ini. tetapi akan berguna untuk mengetahui hal-hal seperti codegolf , tantangan di mana Anda menulis kode terpendek (ternyata Anda bisa menggunakan karakter apa saja tanpa ()). Saya bisa membayangkan beberapa kasus penggunaan nyata di mana perpustakaan menggunakan ini dan Anda perlu menggunakannya bahkan jika mereka tidak bermaksud untuk fungsi itu.

Contoh:

// simple number doubling function
f = _=> {
    _ = _ * 2;
    return _;
}

console.log(f(2)); // returns 4
console.log(f(10)); // returns 20

Diuji dengan konsol Chrome, Versi 76.0.3809.132 (Bentukan Resmi) (64-bit)

Matsyir
sumber
1
Garis bawah '_' adalah nama variabel legal dan bukan konstruksi bahasa khusus, hanya diberi arti khusus berdasarkan konvensi. Peringatan Linter tentang parameter yang tidak digunakan dapat dibungkam menggunakan awalan garis bawah. Saya kira _ dengan sendirinya hanyalah cara terpendek untuk mengatakan tidak terpakai.
Hentikan
@Halt Terima kasih atas klarifikasinya, senang mengetahui dengan pasti. Saya sebenarnya tidak menyadari Anda dapat membuat fungsi panah tanpa ()sebelum saya membuat posting ini, saya pikir _itu satu-satunya cara, itulah sebabnya saya memutuskan untuk menunjukkan ini. Dengan pemikiran ini ternyata tidak ada yang istimewa untuk digunakan bahkan untuk bermain golf, karena Anda bisa saja menggunakan karakter biasa. Lebih baik digunakan hanya untuk mengikuti konvensi, seperti yang Anda katakan.
Matsyir