Halo, Habr!
Sampai hari ini, saya hanya menerjemahkan artikel yang menarik menurut penulis berbahasa Inggris. Dan sekarang saatnya untuk menulis sesuatu sendiri. Untuk artikel pertama, saya memilih topik yang, saya yakin, akan bermanfaat bagi pengembang junior yang ingin berkembang ke "menengah", karena itu akan menganalisis kesamaan / perbedaan antara JavaScript dan bahasa pemrograman klasik (C ++, C #, Java) dalam hal OOP. Jadi mari kita mulai!
Ketentuan umum paradigma
Jika kita melihat definisi JavaScript di
Wikipedia , kita akan melihat konsep berikut:
JavaScript (/ ˈdʒɑːvɑːˌskrɪpt /; abbr. JS /ˈdʒeɪ.ɛs./) adalah bahasa pemrograman multi-paradigma. Mendukung gaya berorientasi objek, imperatif dan fungsional. Ini adalah implementasi dari bahasa ECMAScript (standar ECMA-262).
Sebagai berikut dari definisi ini, JavaScript tidak ada dengan sendirinya, tetapi merupakan implementasi dari beberapa spesifikasi EcmaScript. Selain itu, bahasa lain menerapkan spesifikasi ini.
Paradigma berikut ini hadir dalam EcmaScript (selanjutnya disebut ES):
- struktural
- OOP
- fungsional
- sangat penting
- berorientasi pada aspek (dalam kasus yang jarang terjadi)
OOP dalam ES diimplementasikan pada
organisasi prototipe . Dari pengembang pemula menanggapi pertanyaan: "Bagaimana OOP di JS berbeda dari OOP dalam bahasa klasik." Sebagai aturan, mereka menjadi sangat samar: "Kelas dalam bahasa klasik, dan prototipe dalam JS".
Pada kenyataannya, situasinya sedikit lebih rumit. Dalam hal perilaku, perbedaan antara
Organisasi Kelas Dinamis dan
Organisasi Prototipe kecil (pasti ada, tetapi tidak begitu global).
Lihatlah Python atau Ruby. Dalam bahasa-bahasa ini, OOP didasarkan pada organisasi kelas yang dinamis. Dalam kedua bahasa ini, kita dapat secara dinamis mengubah kelas suatu objek saat program berlangsung dan perubahan di dalam kelas juga secara dinamis memengaruhi entitas yang dihasilkannya. Sama seperti di JS, tetapi di JS, OOP didasarkan pada prototipe.
Perbedaan signifikan antara bahasa dengan organisasi kelas statis dan organisasi Prototipe. Perbedaannya sendiri adalah “ada kelas. di sini prototipe ”tidak begitu signifikan.
Apa yang dimaksud dengan Organisasi Kelas Statis?
Dasar dari tipe OOP ini adalah konsep "Kelas" dan "Esensi".
Kelas adalah seperangkat karakteristik umum terformalisasi tertentu yang dapat dihasilkannya. Yaitu ini adalah rencana umum tertentu dari semua objek yang dihasilkannya.
Karakteristik ada dua jenis. Properti (deskripsi entitas) dan metode (aktivitas entitas, perilaku mereka).
Entitas yang dihasilkan oleh suatu kelas adalah salinan dari kelas ini, tetapi dengan properti yang diinisialisasi. Seperti yang kita lihat, kelas secara ketat mengatur deskripsi suatu entitas (menyediakan seperangkat properti yang didefinisikan secara ketat) dan perilakunya (memberikan daftar metode yang didefinisikan secara ketat).
Berikut adalah contoh kecil di JAWA:
class Person{ String name;
Sekarang buat instance kelas:
public class Program{ public static void main(String[] args) { Person tom; } }
Entitas
tom kami memiliki semua karakteristik kelas
Person , ia juga memiliki semua metode kelasnya.
Paradigma OOP menyediakan palet yang sangat luas kemungkinan untuk menggunakan kembali kode, salah satu fitur ini adalah
Warisan .
Satu kelas dapat memperluas kelas lain, sehingga menciptakan hubungan generalisasi-spesialisasi. Dalam hal ini, sifat-sifat kelas umum (superclass) disalin ke esensi kelas turunan ketika mereka dibuat, dan metode tersedia dengan referensi (oleh rantai pewarisan hirarkis). Dalam hal pengetikan kelas statis, rantai ini bersifat
statis , dan dalam kasus pengetikan dinamis, rantai ini dapat berubah selama eksekusi program. Inilah perbedaan terpenting. Saya menyarankan Anda sekarang untuk mengingat momen ini. Lebih jauh, ketika kita sampai di organisasi Prototipe, esensi dari masalah jawaban "ada kelas, lalu prototipe" akan menjadi jelas.
Apa kerugian dari pendekatan ini?
Saya pikir sudah jelas bahwa:
- Intinya, mungkin ada karakteristik yang tidak akan pernah berguna.
- Kelas tidak dapat secara dinamis mengubah, menambah, menghapus properti dan metode yang disediakannya untuk entitas yang dihasilkan, yaitu tidak dapat mengubah tanda tangannya.
- Pada dasarnya, properti atau metode yang tidak ada di kelas induk (atau rantai hierarkis orang tua) tidak bisa ada
- Konsumsi memori sebanding dengan jumlah tautan dalam hierarki warisan (karena menyalin properti)
Apa yang menjadi dasar organisasi prototipe?
Konsep kunci dari organisasi prototipe adalah objek yang dapat berubah dinamis (dmo). DMO tidak membutuhkan kelas. Dia sendiri dapat menyimpan semua properti dan metodenya.
Saat menetapkan DMO properti, ia memeriksa keberadaan properti ini di dalamnya. Jika ada properti, maka itu hanya ditugaskan, jika tidak, maka properti ditambahkan dan diinisialisasi dengan nilai yang diteruskan. DMO dapat mengubah tanda tangan mereka selama program sesering mungkin.
Berikut ini sebuah contoh:
Saya pikir semua orang dalam subjek tahu bahwa sintaksis kelas telah muncul dalam ES6, tetapi ini tidak lebih dari gula sintaksis, yaitu. prototipe di bawah tenda. Kode di atas tidak boleh dianggap sebagai praktik pengkodean yang baik. Ini tidak lebih dari sebuah ilustrasi, itu disajikan dalam bentuk ini (sekarang semua orang normal menggunakan kelas ES6) agar tidak membingungkan pembaca dan menekankan perbedaan dalam konsep-konsep teoritis.
Jika kita menampilkan objek Tom ke konsol, kita akan melihat bahwa objek itu sendiri hanya memiliki tautan _proto_, yang selalu ada di dalamnya secara default. Referensi menunjuk ke objek Person, yang merupakan prototipe dari objek Tom.
Prototipe adalah objek yang berfungsi sebagai prototipe untuk objek lain atau objek di mana objek lain dapat menggambar properti dan metode jika diperlukan.
Prototipe untuk suatu objek dapat berupa objek apa saja, apalagi, objek dapat menugaskan kembali prototipe selama program.
Mari kita kembali ke Tom kita:
Tom.name = 'Tom';
Perhatikan bahwa nama, properti usia dan metode sayHi adalah properti dari objek tomSon. Pada saat yang sama, kami di tomSon sayHi secara eksplisit memanggil metode prototipe sayHi seolah-olah itu ada di objek Tom, tetapi sebenarnya tidak ada di sana, dan mengembalikan secara implisit dari prototipe Person. Kami juga secara eksplisit beroperasi pada nama properti prototipe dan secara implisit mendapatkan properti marga, yang kita sebut sebagai milik kita sendiri dari objek tomSon, tetapi sebenarnya tidak ada di sana. Properti marga secara implisit ditarik melalui tautan
__proto__ dari prototipe.
Kami melanjutkan perkembangan sejarah Tom dan putranya John.
Harap dicatat bahwa selama program kami mengubah prototipe objek yang sudah dibuat. Ini adalah kesamaan
Organisasi Prototipe dan
Organisasi Kelas Dinamis . Itu sebabnya jawaban "ada kelas, ada prototipe" untuk pertanyaan "apa perbedaan antara bahasa klasik dan JavaScript?" tidak cukup benar dan menunjukkan beberapa kesalahpahaman tentang teori OOP dan implementasinya pada kelas dan / atau prototipe.
Dengan organisasi Prototipe, tidak seperti kelas Static, kami memiliki kesempatan untuk membuat perubahan pada prototipe setelah membuat entitas yang mewarisi properti dari prototipe ini, dan perubahan ini akan memengaruhi entitas yang sudah dibuat.
Ben.hobbies = ['chess', 'badminton'];
Ini disebut
model pendelegasian organisasi prototipe atau
pewarisan prototipe .
Bagaimana kemampuan suatu entitas untuk menerapkan perilaku tertentu ditentukan?
Dalam organisasi kelas statis, operasi ini melibatkan memeriksa entitas untuk keanggotaan dalam kelas tertentu yang mengimplementasikan perilaku yang diperlukan. Dalam organisasi prototipe, ada konsep
mengetik bebek . Dalam kasus mengetik bebek, memeriksa entitas untuk kemampuan menerapkan perilaku tertentu berarti secara langsung menguji entitas untuk kemampuan menerapkan perilaku ini pada titik waktu tertentu, yaitu. di berbagai bagian program, hasil pemeriksaan mungkin berlawanan secara diametral.
Apa keuntungan dari pendekatan prototipe?
- Lebih banyak fleksibilitas
- Entitas tidak memiliki properti yang tidak mereka butuhkan.
Apa kerugiannya?
- Kurang jelas
- Tidak selalu mudah untuk melacak apa yang berfungsi sebagai titik awal untuk perilaku entitas yang tidak diinginkan, yaitu. prototipe kurang dapat diprediksi daripada organisasi kelas statis
- Komunitas pengembangan perangkat lunak tidak cukup akrab dengannya, terlepas dari popularitas dan prevalensi JavaScript
Kesimpulan
Kita akan mengakhiri hari ini. Saya harap saya dapat menyampaikan gagasan bahwa perbedaan antara bahasa klasik dan JavaScript tidak terkait dengan ada / tidaknya kelas dan ada / tidaknya prototipe, tetapi lebih kepada sifat statis / dinamis organisasi.
Tentu saja, banyak yang belum dipertimbangkan. Saya tidak ingin menulis artikel yang terlalu panjang, jadi kami akan membahas fitur Model Cascade di organisasi prototipe dan alat OOP (Polimorfisme, Enkapsulasi, Abstraksi, dll.) Di artikel selanjutnya.