Menurut proposal itu , panah bertujuan "untuk mengatasi dan menyelesaikan beberapa titik sakit tradisional yang umum Function Expression
." Mereka bermaksud memperbaiki masalah dengan mengikatthis
secara leksikal dan menawarkan sintaksis singkat.
Namun,
- Seseorang tidak dapat mengikat secara konsisten
this
leksikal
- Sintaks fungsi panah halus dan ambigu
Oleh karena itu, fungsi panah menciptakan peluang untuk kebingungan dan kesalahan, dan harus dikeluarkan dari kosakata programmer JavaScript, diganti dengan function
secara eksklusif.
Mengenai leksikal this
this
bermasalah:
function Book(settings) {
this.settings = settings;
this.pages = this.createPages();
}
Book.prototype.render = function () {
this.pages.forEach(function (page) {
page.draw(this.settings);
}, this);
};
Fungsi panah bermaksud untuk memperbaiki masalah di mana kita perlu mengakses properti this
di dalam panggilan balik. Sudah ada beberapa cara untuk melakukan itu: Seseorang dapat menetapkan this
untuk variabel, menggunakan bind
, atau menggunakan argumen ke-3 yang tersedia pada Array
metode agregat. Namun panah tampaknya merupakan solusi yang paling sederhana, sehingga metode ini dapat di refactored seperti ini:
this.pages.forEach(page => page.draw(this.settings));
Namun, pertimbangkan jika kode tersebut menggunakan pustaka seperti jQuery, yang metodenya mengikat this
secara khusus. Sekarang, ada dua this
nilai yang harus dihadapi:
Book.prototype.render = function () {
var book = this;
this.$pages.each(function (index) {
var $page = $(this);
book.draw(book.currentPage + index, $page);
});
};
Kita harus menggunakan function
agar each
mengikatthis
secara dinamis. Kami tidak dapat menggunakan fungsi panah di sini.
Berurusan dengan banyak this
nilai juga bisa membingungkan, karena sulit untuk mengetahui this
penulis mana yang dibicarakan:
function Reader() {
this.book.on('change', function () {
this.reformat();
});
}
Apakah penulis sebenarnya bermaksud menelepon Book.prototype.reformat
? Atau apakah dia lupa mengikat this
, dan berniat menelepon Reader.prototype.reformat
? Jika kita mengubah penangan ke fungsi panah, kita juga akan bertanya-tanya apakah penulis menginginkan dinamika this
, namun memilih panah karena sesuai pada satu baris:
function Reader() {
this.book.on('change', () => this.reformat());
}
Seseorang dapat berpose: "Apakah luar biasa bahwa panah kadang-kadang bisa menjadi fungsi yang salah untuk digunakan? Mungkin jika kita jarang membutuhkan dinamika this
nilai-nilai , maka sebagian besar waktu akan tetap oke untuk menggunakan panah."
Tetapi tanyakan pada diri sendiri ini: "Apakah 'layak' untuk men-debug kode dan menemukan bahwa hasil dari kesalahan dibawa oleh 'kasus tepi?'" Saya lebih suka menghindari masalah bukan hanya sebagian besar waktu, tetapi 100% dari waktu.
Ada cara yang lebih baik: Selalu gunakan function
(jadi this
selalu bisa terikat secara dinamis), dan selalu referensi this
melalui variabel. Variabel leksikal dan mengasumsikan banyak nama. Menetapkan this
ke variabel akan membuat niat Anda jelas:
function Reader() {
var reader = this;
reader.book.on('change', function () {
var book = this;
book.reformat();
reader.reformat();
});
}
Selain itu, selalu menugaskan this
ke variabel (bahkan ketika ada satu this
atau tidak ada fungsi lain) memastikan niat seseorang tetap jelas bahkan setelah kode diubah.
Juga, dinamis this
hampir tidak luar biasa. jQuery digunakan di lebih dari 50 juta situs web (pada tulisan ini pada Februari 2016). Berikut adalah API lain yang mengikat this
secara dinamis:
- Mocha (~ 120k unduhan kemarin) memaparkan metode untuk pengujiannya via
this
.
- Grunt (~ 63k unduhan kemarin) memaparkan metode untuk membangun tugas melalui
this
.
- Backbone (~ 22k unduhan kemarin) mendefinisikan metode mengakses
this
.
- API acara (seperti DOM) merujuk ke
EventTarget
dengan this
.
- API prototipe yang ditambal atau diperluas merujuk ke instance dengan
this
.
(Statistik via http://trends.builtwith.com/javascript/jQuery dan https://www.npmjs.com .)
Anda kemungkinan sudah membutuhkan this
binding dinamis .
Leksikal this
kadang-kadang diharapkan, tetapi kadang-kadang tidak; sama seperti dinamika this
kadang-kadang diharapkan, tetapi kadang tidak. Syukurlah, ada cara yang lebih baik, yang selalu menghasilkan dan mengomunikasikan ikatan yang diharapkan.
Mengenai sintaks singkat
Fungsi panah berhasil menyediakan "bentuk sintaksis pendek" untuk fungsi. Tetapi apakah fungsi yang lebih pendek ini akan membuat Anda lebih sukses?
Apakah x => x * x
"lebih mudah dibaca" daripada function (x) { return x * x; }
? Mungkin begitu, karena lebih mungkin menghasilkan satu baris kode pendek. Mengakses pada Dyson Pengaruh kecepatan membaca dan panjang garis pada efektivitas membaca dari layar ,
Panjang garis sedang (55 karakter per baris) muncul untuk mendukung pembacaan yang efektif pada kecepatan normal dan cepat. Ini menghasilkan tingkat pemahaman tertinggi. . .
Pembenaran serupa dibuat untuk operator bersyarat (ternary), dan untuk if
pernyataan garis tunggal .
Namun, apakah Anda benar-benar menulis fungsi matematika sederhana yang diiklankan dalam proposal ? Domain saya bukan matematika, jadi subrutin saya jarang begitu elegan. Sebaliknya, saya biasanya melihat fungsi panah melanggar batas kolom, dan membungkus ke baris lain karena editor atau panduan gaya, yang membatalkan "keterbacaan" oleh definisi Dyson.
Seseorang mungkin berpose, "Bagaimana kalau hanya menggunakan versi pendek untuk fungsi pendek, bila memungkinkan?" Tetapi sekarang aturan gaya bertentangan dengan batasan bahasa: "Cobalah menggunakan notasi fungsi sesingkat mungkin, ingatlah bahwa kadang-kadang hanya notasi terpanjang yang akan mengikatthis
seperti yang diharapkan." Penggabungan seperti itu membuat anak panah rentan terhadap penyalahgunaan.
Ada banyak masalah dengan sintaks fungsi panah:
const a = x =>
doSomething(x);
const b = x =>
doSomething(x);
doSomethingElse(x);
Kedua fungsi ini valid secara sintaksis. Tetapi doSomethingElse(x);
tidak ada di dalam tubuh b
, itu hanya pernyataan tingkat atas yang indentasi buruk.
Ketika memperluas ke bentuk blok, tidak ada lagi yang tersirat return
, yang orang bisa lupa untuk mengembalikan. Tetapi ungkapan itu mungkin hanya dimaksudkan untuk menghasilkan efek samping, jadi siapa yang tahu jika diperlukan eksplisit return
untuk maju?
const create = () => User.create();
const create = () => {
let user;
User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
const create = () => {
let user;
return User.create().then(result => {
user = result;
return sendEmail();
}).then(() => user);
};
Apa yang mungkin dimaksudkan sebagai parameter lainnya dapat diurai sebagai operator spread:
processData(data, ...results => {}) // Spread
processData(data, (...results) => {}) // Rest
Tugas dapat dikacaukan dengan argumen default:
const a = 1;
let x;
const b = x => {}; // No default
const b = x = a => {}; // "Adding a default" instead creates a double assignment
const b = (x = a) => {}; // Remember to add parens
Blok terlihat seperti objek:
(id) => id // Returns `id`
(id) => {name: id} // Returns `undefined` (it's a labeled statement)
(id) => ({name: id}) // Returns an object
Apa artinya ini?
() => {}
Apakah penulis bermaksud membuat no-op, atau fungsi yang mengembalikan objek kosong? (Dengan mengingat hal ini, haruskah kita menempatkan {
setelah =>
? Haruskah kita membatasi diri kita hanya pada sintaks ekspresi? Itu akan semakin mengurangi frekuensi panah.)
=>
terlihat seperti <=
dan >=
:
x => 1 ? 2 : 3
x <= 1 ? 2 : 3
if (x => 1) {}
if (x >= 1) {}
Untuk memunculkan ekspresi fungsi panah dengan segera, seseorang harus menempatkan ()
di luar, namun menempatkan ()
di dalam adalah valid dan bisa disengaja.
(() => doSomething()()) // Creates function calling value of `doSomething()`
(() => doSomething())() // Calls the arrow function
Meskipun, jika seseorang menulis (() => doSomething()());
dengan maksud untuk menulis ekspresi fungsi yang segera dipanggil, tidak ada yang akan terjadi.
Sulit untuk berpendapat bahwa fungsi panah "lebih dapat dimengerti" dengan semua kasus di atas dalam pikiran. Seseorang dapat mempelajari semua aturan khusus yang diperlukan untuk menggunakan sintaks ini. Apakah ini benar-benar layak?
Sintaksnya function
digeneralisasikan secara tidak terduga. Untuk menggunakan function
secara eksklusif berarti bahasa itu sendiri mencegah seseorang dari menulis kode yang membingungkan. Untuk menulis prosedur yang harus dipahami secara sintaksis dalam semua kasus, saya memilih function
.
Tentang pedoman
Anda meminta pedoman yang harus "jelas" dan "konsisten." Menggunakan fungsi panah pada akhirnya akan menghasilkan kode yang valid secara sintaksis, tidak logis secara logis, dengan kedua bentuk fungsi saling terkait, bermakna dan sewenang-wenang. Karena itu, saya menawarkan yang berikut:
Pedoman untuk Notasi Fungsi di ES6:
- Selalu buat prosedur dengan
function
.
- Selalu tetapkan
this
ke variabel. Jangan gunakan () => {}
.
Fixed this bound to scope at initialisation
sebagai batasan?