Metaprogramming dalam JavaScript dan TypeScript

Prolog


Saya ingin mempersembahkan kepada Anda sejumlah patung mini yang akan menjelaskan teknik dan dasar-dasar pemograman. Saya terutama akan menulis tentang penggunaan teknik-teknik tertentu dalam JavaScript atau dalam TypeScript
Ini adalah artikel pertama (dan mudah-mudahan bukan yang terakhir) dalam seri ini.


Jadi, apa itu pemrograman?


Metaprogramming adalah teknik pemrograman di mana program komputer memiliki kemampuan untuk memperlakukan program lain sebagai datanya. Ini berarti bahwa suatu program dapat dirancang untuk membaca, menghasilkan, menganalisis atau mengubah program lain, dan bahkan memodifikasi sendiri saat berjalan. Dalam beberapa kasus, ini memungkinkan programmer untuk meminimalkan jumlah baris kode untuk mengekspresikan solusi, yang pada gilirannya mengurangi waktu pengembangan .

Deskripsi yang agak membingungkan, tetapi manfaat utama dari pemrograman metaf dapat dimengerti:


... ini memungkinkan programmer untuk meminimalkan jumlah baris kode untuk mengimplementasikan solusi, yang pada gilirannya mengurangi waktu pengembangan


Bahkan, metaprogramming memiliki banyak wajah dan kedok. Dan Anda dapat berdiskusi untuk waktu yang lama tentang "di mana metaprogramming berakhir dan pemrograman itu sendiri dimulai"


Bagi saya sendiri, saya menerima aturan berikut:


  1. Metaprogramming tidak berurusan dengan logika bisnis, tidak mengubahnya, dan tidak mempengaruhinya dengan cara apa pun.
  2. Jika Anda menghapus semua kode pemrograman, ini seharusnya tidak (secara radikal) memengaruhi program.

Dalam JavaScript, metaprogramming adalah tren yang relatif baru, batu bata dasarnya adalah deskriptor.


Deskriptor JavaScript


Deskriptor adalah sejenis deskripsi (meta informasi) dari properti atau metode tertentu dalam suatu objek.


Memahami dan memanipulasi objek ini dengan benar ( deskriptor ) memungkinkan lebih dari sekedar membuat dan mengubah metode atau properti dalam objek.
Juga deskriptor akan membantu dalam memahami pekerjaan dengan dekorator (tetapi lebih banyak tentang itu di artikel berikutnya).


Untuk lebih jelasnya, bayangkan objek kita adalah deskripsi apartemen.
Kami menggambarkan objek apartemen kami:


let apt = { floor: 12, number: '12B', size: 3400, bedRooms: 3.4, bathRooms: 2, price: 400000, amenities: {...} }; 

Mari kita tentukan properti mana yang dapat dimodifikasi dan mana yang tidak.


Misalnya, lantai atau ukuran total apartemen tidak dapat diubah, tetapi jumlah kamar atau kamar mandi sangat mungkin.
Dan jadi kami memiliki persyaratan berikut: pada objek yang tepat , membuatnya tidak mungkin untuk mengubah sifat: lantai dan ukuran .


Untuk mengatasi masalah ini, kita hanya perlu deskriptor dari masing-masing properti ini. Untuk mendapatkan descriptor , kami menggunakan metode statis getOwnPropertyDescriptor , yang dimiliki oleh Object kelas.


 let descriptor = Object.getOwnPropertyDescriptor(todoObject, 'floor'); console.log(descriptor); // Output { value: 12, writable: true, enumerable: true, configurable: true } 

Mari kita analisis secara berurutan:
value: any - sebenarnya nilai yang sama yang pada titik tertentu ditugaskan ke properti lantai
dapat ditulis: boolean - menentukan apakah akan mengubah nilai atau tidak
enumerable: boolean - menentukan apakah properti lantai dapat terdaftar atau tidak - (lebih lanjut tentang itu nanti).
dapat dikonfigurasi: boolean - Menentukan kemampuan untuk membuat perubahan pada objek deskriptor .


Untuk mencegah kemungkinan mengubah properti lantai , setelah inisialisasi, perlu mengubah nilai yang dapat ditulis menjadi salah .
Untuk mengubah properti deskriptor, ada metode statis defineProperty , yang mengambil objek itu sendiri, nama properti, dan deskriptor .


 Object.defineProperty(apt, 'floor', {writable: false}); 

Dalam contoh ini, kami tidak melewatkan seluruh objek deskriptor , tetapi hanya satu properti yang dapat ditulis dengan nilai false .
Sekarang mari kita coba untuk mengubah nilai di properti lantai:


 apt.floor = 44; console.log(apt.floor); // output 12 

Nilai tidak berubah, dan saat menggunakan 'gunakan ketat' kami menerima pesan kesalahan:


Tidak dapat menetapkan untuk hanya membaca properti 'lantai' objek ...

Dan sekarang kita tidak bisa lagi mengubah nilainya. Namun, kami masih dapat mengembalikan yang dapat ditulisi -> true dan kemudian mengubah properti lantai . Untuk menghindari hal ini, perlu untuk mengubah nilai properti yang dapat dikonfigurasi ke false dalam deskriptor .


 Object.defineProperty(apt, 'floor', {writable: false, configurable: false}); 

Jika sekarang kita mencoba mengubah nilai salah satu properti dari deskriptor kami ...


 Object.defineProperty(apt, 'floor', {writable: true, configurable: true}); 

Sebagai tanggapan, kami mendapatkan:


TypeError: Tidak dapat mendefinisikan ulang properti: lantai
Dengan kata lain, kita tidak bisa lagi mengubah nilai floor atau deskriptornya .

Ringkaslah


Untuk membuat nilai properti di objek tidak berubah, perlu mendaftarkan konfigurasi properti ini: {dapat ditulis: salah, dapat dikonfigurasi: salah} .


Ini dapat dilakukan seperti saat inisialisasi properti:


 Object.defineProperty(apt, 'floor', {value: 12, writable: false, configurable: false}); 

Atau sesudahnya.


 Object.defineProperty(apt, 'floor', {writable: false, configurable: false}); 

Pada akhirnya, pertimbangkan sebuah contoh dengan kelas:


 class Apartment { constructor(apt) { this.apt = apt; } getFloor() { return this.apt.floor } } let apt = { floor: 12, number: '12B', size: 3400, bedRooms: 3.4, bathRooms: 2, price: 400000, amenities: {...} }; 

Ubah metode getFloor:


 Apartment.prototype.getFloor = () => { return 44 }; let myApt = new Apartment(apt); console.log(myApt); // output will be changed. 44 

Sekarang ubah deskriptor metode getFloor () :


 Object.defineProperty(Apartment.prototype, 'getFloor', {writable: false, configurable: false}); Apartment.prototype.getFloor = () => { return 44 }; let myApt = new Apartment(apt); console.log(myApt); // output will be original. 12 

Saya harap artikel ini memberi sedikit lebih banyak keterangan tentang apa itu deskriptor dan bagaimana deskriptor itu dapat digunakan.


Segala sesuatu yang ditulis di atas tidak mengklaim benar-benar benar atau satu-satunya yang benar.

Source: https://habr.com/ru/post/id450540/


All Articles