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 thisdi dalam panggilan balik. Sudah ada beberapa cara untuk melakukan itu: Seseorang dapat menetapkan thisuntuk variabel, menggunakan bind, atau menggunakan argumen ke-3 yang tersedia pada Arraymetode 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 thissecara khusus. Sekarang, ada dua thisnilai 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 functionagar eachmengikatthis secara dinamis. Kami tidak dapat menggunakan fungsi panah di sini.
Berurusan dengan banyak thisnilai juga bisa membingungkan, karena sulit untuk mengetahui thispenulis 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 thisselalu bisa terikat secara dinamis), dan selalu referensi thismelalui variabel. Variabel leksikal dan mengasumsikan banyak nama. Menetapkan thiske 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 thiske variabel (bahkan ketika ada satu thisatau tidak ada fungsi lain) memastikan niat seseorang tetap jelas bahkan setelah kode diubah.
Juga, dinamis thishampir tidak luar biasa. jQuery digunakan di lebih dari 50 juta situs web (pada tulisan ini pada Februari 2016). Berikut adalah API lain yang mengikat thissecara 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
EventTargetdengan 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 thisbinding dinamis .
Leksikal thiskadang-kadang diharapkan, tetapi kadang-kadang tidak; sama seperti dinamika thiskadang-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 ifpernyataan 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 returnuntuk 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 functiondigeneralisasikan secara tidak terduga. Untuk menggunakan functionsecara 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
thiske variabel. Jangan gunakan () => {}.
Fixed this bound to scope at initialisationsebagai batasan?