Saya tidak yakin pendekatan terbaik untuk menangani pelingkupan "ini" di TypeScript.
Berikut adalah contoh pola umum dalam kode yang saya ubah ke TypeScript:
class DemonstrateScopingProblems {
private status = "blah";
public run() {
alert(this.status);
}
}
var thisTest = new DemonstrateScopingProblems();
// works as expected, displays "blah":
thisTest.run();
// doesn't work; this is scoped to be the document so this.status is undefined:
$(document).ready(thisTest.run);
Sekarang, saya dapat mengubah panggilan ke ...
$(document).ready(thisTest.run.bind(thisTest));
... yang berhasil. Tapi itu mengerikan. Ini berarti bahwa kode semua dapat dikompilasi dan berfungsi dengan baik dalam beberapa keadaan, tetapi jika kita lupa untuk mengikat cakupan, itu akan rusak.
Saya ingin cara melakukannya di dalam kelas, sehingga saat menggunakan kelas kita tidak perlu khawatir tentang cakupan "ini".
Ada saran?
Memperbarui
Pendekatan lain yang berhasil adalah menggunakan panah gemuk:
class DemonstrateScopingProblems {
private status = "blah";
public run = () => {
alert(this.status);
}
}
Apakah itu pendekatan yang valid?
typescript
this
Jonathan Moffatt
sumber
sumber
Jawaban:
Anda memiliki beberapa opsi di sini, masing-masing dengan keuntungannya sendiri. Sayangnya tidak ada solusi terbaik yang jelas dan itu akan sangat bergantung pada aplikasi.
Pengikatan Kelas Otomatis
Seperti yang ditunjukkan dalam pertanyaan Anda:
this
konteks daripada setiap situs panggilan membuat penutupan baru saat dipanggil.this
kontekssuper.
Function.bind
Juga seperti yang ditunjukkan:
Panah gemuk
Dalam TypeScript (ditampilkan di sini dengan beberapa parameter tiruan untuk alasan penjelasan):
sumber
Solusi lain yang membutuhkan beberapa pengaturan awal tetapi terbayar dengan cahaya yang tak terkalahkan, secara harfiah sintaks satu kata menggunakan Metode Dekorator untuk mengikat JIT metode melalui getter.
Saya telah membuat repo di GitHub untuk memamerkan implementasi ide ini (agak panjang untuk memasukkan jawaban dengan 40 baris kode, termasuk komentar) , yang akan Anda gunakan sesederhana:
Saya belum melihat ini disebutkan di mana pun, tetapi berfungsi dengan sempurna. Selain itu, tidak ada kerugian penting untuk pendekatan ini: penerapan dekorator ini - termasuk beberapa pemeriksaan jenis untuk keamanan jenis runtime - adalah hal yang sepele dan mudah, dan pada dasarnya dilengkapi dengan overhead nol setelah pemanggilan metode awal.
Bagian penting adalah mendefinisikan pengambil berikut pada prototipe kelas, yang dijalankan segera sebelum panggilan pertama:
Sumber lengkap
Idenya juga dapat dibawa selangkah lebih maju, dengan melakukan ini di dekorator kelas, mengiterasi metode dan menentukan deskriptor properti di atas untuk masing-masing metode dalam satu proses.
sumber
Necromancing.
Ada solusi sederhana yang jelas yang tidak memerlukan fungsi panah (fungsi panah 30% lebih lambat), atau metode JIT melalui getter.
Solusi itu adalah mengikat konteks-ini di konstruktor.
Anda dapat menulis metode autobind untuk mengikat semua fungsi secara otomatis dalam konstruktor kelas:
Perhatikan bahwa jika Anda tidak menempatkan fungsi autobind ke dalam kelas yang sama sebagai fungsi anggota, itu adil
autoBind(this);
dan tidakthis.autoBind(this);
Dan juga, fungsi autoBind di atas dibodohi, untuk menunjukkan prinsip.
Jika Anda ingin ini berfungsi dengan andal, Anda perlu menguji apakah fungsinya adalah pengambil / penyetel properti juga, karena sebaliknya - boom - jika kelas Anda berisi properti, begitulah.
Seperti ini:
sumber
Dalam kode Anda, sudahkah Anda mencoba mengubah baris terakhir sebagai berikut?
sumber