Di TypeScript 3.8+, apa perbedaan antara menggunakan private
kata kunci untuk menandai pribadi anggota:
class PrivateKeywordClass {
private value = 1;
}
Dan menggunakan #
bidang pribadi yang diusulkan untuk JavaScript :
class PrivateFieldClass {
#value = 1;
}
Haruskah saya lebih suka yang satu daripada yang lain?
javascript
typescript
class
encapsulation
Matt Bierner
sumber
sumber
Jawaban:
Kata kunci pribadi
Kata kunci pribadi dalam TypeScript adalah anotasi waktu kompilasi . Ini memberitahu kompiler bahwa properti hanya dapat diakses di dalam kelas itu:
Namun kompilasi pengecekan waktu dapat dengan mudah dilewati, misalnya dengan membuang informasi jenis:
Itu
private
kunci juga tidak diberlakukan saat runtimeJavaScript yang Dipancarkan
Saat mengkompilasi TypeScript ke JavaScript,
private
kata kunci dihapus:Menjadi:
Dari ini, Anda dapat melihat mengapa
private
kata kunci tidak menawarkan perlindungan runtime: di JavaScript yang dihasilkan itu hanya properti JavaScript normal.Bidang pribadi
Bidang pribadi memastikan bahwa properti dirahasiakan saat runtime :
TypeScript juga akan menampilkan kesalahan waktu kompilasi jika Anda mencoba menggunakan bidang pribadi di luar kelas:
Bidang pribadi berasal dari proposal JavaScript dan juga berfungsi dalam JavaScript normal.
JavaScript yang Dipancarkan
Jika Anda menggunakan bidang pribadi dalam TypeScript dan menargetkan versi JavaScript yang lebih lama untuk hasil Anda, seperti
es6
ataues2018
, TypeScript akan mencoba membuat kode yang mengemulasi perilaku runtime bidang pribadiJika Anda menargetkan
esnext
, TypeScript akan memancarkan bidang pribadi:Yang mana yang harus saya gunakan?
Itu tergantung pada apa yang ingin Anda capai.
Kata
private
kunci adalah standar yang baik. Itu mencapai apa yang dirancang untuk dicapai dan telah berhasil digunakan oleh pengembang TypeScript selama bertahun-tahun. Dan jika Anda memiliki basis kode yang ada, Anda tidak perlu mengalihkan semua kode Anda untuk menggunakan bidang pribadi. Ini terutama benar jika Anda tidak menargetkanesnext
, karena JS yang dipancarkan TS untuk bidang pribadi mungkin memiliki dampak kinerja. Juga perlu diingat bahwa bidang pribadi memiliki perbedaan halus namun penting lainnya dariprivate
kata kunciNamun jika Anda perlu menegakkan privasi runtime atau mengeluarkan
esnext
JavaScript, Anda harus menggunakan bidang pribadi.Perlu diingat juga bahwa konvensi organisasi / komunitas tentang penggunaan satu atau yang lain juga akan berkembang ketika bidang pribadi menjadi lebih luas dalam ekosistem JavaScript / TypeScript
Perbedaan catatan lainnya
Bidang pribadi tidak dikembalikan oleh
Object.getOwnPropertyNames
dan metode serupaBidang pribadi tidak diserialisasi oleh
JSON.stringify
Ada kasus tepi penting di sekitar warisan.
TypeScript misalnya melarang menyatakan properti pribadi di subkelas dengan nama yang sama dengan properti pribadi di superclass.
Ini tidak benar dengan bidang pribadi:
Sebuah
private
milik pribadi kunci tanpa initializer tidak akan menghasilkan deklarasi properti di dipancarkan JavaScript:Kompilasi ke:
Sedangkan bidang pribadi selalu menghasilkan deklarasi properti:
Kompilasi ke (saat menargetkan
esnext
):Bacaan lebih lanjut:
sumber
Gunakan kasing:
#
bidang -privateKata pengantar:
#
-private, hard private, run-time privatePrivasi waktu kompilasi dan run-time
#
bidang -private menyediakan privasi waktu kompilasi dan run-time, yang tidak "bisa diretas". Ini adalah mekanisme untuk mencegah akses ke anggota dari luar badan kelas dengan cara langsung apa pun .Warisan kelas yang aman
#
Bidang -private mendapatkan cakupan yang unik. Hirarki kelas dapat diimplementasikan tanpa ditimpa secara tidak sengaja properti pribadi dengan nama yang sama.Kompiler TS untungnya memancarkan kesalahan, ketika
private
properti dalam bahaya ditimpa (lihat contoh ini ). Tetapi karena sifat fitur kompilasi-waktu semuanya masih mungkin pada saat dijalankan, mengingat kesalahan kompilasi diabaikan dan / atau kode JS yang dipancarkan digunakan.Perpustakaan eksternal
Penulis perpustakaan dapat melakukan refactor
#
pengidentifikasi pribadi tanpa menyebabkan perubahan besar bagi klien. Pengguna perpustakaan di sisi lain dilindungi dari mengakses bidang internal.API JS menghilangkan
#
bidang -privateFungsi dan metode JS
#
bawaan mengabaikan bidang -privat. Ini dapat menghasilkan pemilihan properti yang lebih mudah diprediksi pada saat run-time. Contoh:Object.keys
,Object.entries
,JSON.stringify
,for..in
lingkaran dan lain-lain ( kode contoh , lihat juga Matt Bierner ini jawaban ):Gunakan kasus:
private
kata kunciKata pengantar:
private
kata kunci dalam TS docsAkses ke API kelas internal dan status (kompilasi waktu saja privasi)
private
anggota kelas adalah properti konvensional pada saat run-time. Kita dapat menggunakan fleksibilitas ini untuk mengakses API internal kelas atau status dari luar. Untuk memenuhi pemeriksaan kompiler, mekanisme seperti jenis pernyataan, akses properti dinamis atau@ts-ignore
dapat digunakan antara lain.Contoh dengan jenis pernyataan (
as
/<>
) danany
tugas variabel yang diketik:TS bahkan memungkinkan akses properti dinamis dari
private
anggota dengan jalan keluar :Di mana akses pribadi masuk akal? (1) tes unit, (2) situasi debugging / logging atau (3) skenario kasus lanjutan lainnya dengan kelas proyek-internal (daftar terbuka).
Akses ke variabel internal agak kontradiktif - jika tidak, Anda tidak akan membuatnya
private
di tempat pertama. Sebagai contoh, pengujian unit seharusnya berupa kotak hitam / abu-abu dengan bidang pribadi disembunyikan sebagai detail implementasi. Namun dalam praktiknya, mungkin ada pendekatan yang valid dari kasus ke kasus.Tersedia di semua lingkungan ES
private
Pengubah TS dapat digunakan dengan semua target ES.#
Bidang -private hanya tersedia untuktarget
ES2015
/ES6
atau lebih tinggi. Dalam ES6 +,WeakMap
digunakan secara internal sebagai implementasi tingkat bawah (lihat di sini ). Asli#
bidang-swasta saat ini membutuhkantarget
esnext
.Konsistensi dan kompatibilitas
Tim mungkin menggunakan pedoman pengkodean dan aturan linter untuk menegakkan penggunaan
private
sebagai satu-satunya pengubah akses. Pembatasan ini dapat membantu dengan konsistensi dan menghindari kebingungan dengan#
notasi bidang -private dengan cara yang kompatibel dengan mundur.Jika diperlukan, properti parameter (singkatan penugasan konstruktor) adalah penghenti acara. Mereka hanya dapat digunakan dengan
private
kata kunci dan tidak ada rencana untuk mengimplementasikannya untuk#
bidang -privat.Alasan lain
private
mungkin memberikan kinerja run-time yang lebih baik dalam beberapa kasus down-leveling (lihat di sini ).private
notasi kata kunci yang lebih baik 😊.Perhatikan keduanya
Kedua pendekatan menciptakan semacam jenis nominal atau merek pada waktu kompilasi.
Juga, keduanya memungkinkan akses lintas-instance: instance dari kelas
A
dapat mengakses anggota pribadi dariA
instance lain :Sumber
sumber