Jadi saya akhirnya berhenti menyeret kaki saya selama bertahun-tahun dan memutuskan untuk belajar JavaScript "dengan benar". Salah satu elemen yang paling menggaruk-garuk dari desain bahasa adalah implementasi warisan. Memiliki pengalaman di Ruby, saya sangat senang melihat penutupan dan pengetikan dinamis; tetapi untuk kehidupan saya tidak tahu manfaat apa yang bisa didapat dari instance objek menggunakan instance lain untuk warisan.
271
Jawaban:
Saya tahu bahwa jawaban ini terlambat 3 tahun tetapi saya benar-benar berpikir jawaban saat ini tidak memberikan informasi yang cukup tentang bagaimana pewarisan prototypal lebih baik daripada warisan klasik .
Pertama mari kita lihat argumen paling umum yang menyatakan programmer JavaScript dalam membela pewarisan prototypal (Saya mengambil argumen ini dari kumpulan jawaban saat ini):
Sekarang argumen ini semuanya valid, tetapi tidak ada yang peduli menjelaskan mengapa. Ini seperti memberi tahu seorang anak bahwa belajar Matematika itu penting. Tentu saja, tetapi anak itu tentu saja tidak peduli; dan Anda tidak dapat membuat anak seperti Matematika dengan mengatakan bahwa itu penting.
Saya pikir masalah dengan pewarisan prototypal adalah bahwa hal itu dijelaskan dari perspektif JavaScript. Saya suka JavaScript, tetapi warisan prototipal dalam JavaScript salah. Tidak seperti pewarisan klasik ada dua pola pewarisan prototypal:
Sayangnya JavaScript menggunakan pola konstruktor dari warisan prototypal. Ini karena ketika JavaScript dibuat, Brendan Eich (pembuat JS) ingin agar terlihat seperti Java (yang memiliki warisan klasik):
Ini buruk karena ketika orang menggunakan konstruktor dalam JavaScript mereka memikirkan konstruktor yang diwarisi dari konstruktor lain. Ini salah. Dalam purwarupa objek prototypal mewarisi dari objek lain. Konstruktor tidak pernah masuk ke dalam gambar. Inilah yang membingungkan kebanyakan orang.
Orang-orang dari bahasa seperti Jawa, yang memiliki warisan klasik, menjadi semakin bingung karena walaupun konstruktor terlihat seperti kelas, mereka tidak berperilaku seperti kelas. Seperti yang dinyatakan Douglas Crockford :
Itu dia. Langsung dari mulut kuda.
Warisan Prototypal Sejati
Warisan prototipe adalah tentang benda. Objek mewarisi properti dari objek lain. Hanya itu yang ada untuk itu. Ada dua cara membuat objek menggunakan warisan prototypal:
Catatan: JavaScript menawarkan dua cara untuk mengkloning objek - delegasi dan penggabungan . Selanjutnya saya akan menggunakan kata "clone" untuk secara eksklusif merujuk pada pewarisan melalui delegasi, dan kata "copy" untuk secara eksklusif merujuk pada pewarisan melalui penggabungan.
Cukup bicara. Mari kita lihat beberapa contoh. Katakanlah saya memiliki lingkaran jari-jari
5
:Kita dapat menghitung luas dan keliling lingkaran dari jari-jarinya:
Sekarang saya ingin membuat lingkaran jari-jari lain
10
. Salah satu cara untuk melakukan ini adalah:Namun JavaScript menyediakan cara yang lebih baik - delegasi . The
Object.create
Fungsi ini digunakan untuk melakukan hal ini:Itu saja. Anda baru saja melakukan pewarisan prototipal dalam JavaScript. Bukankah itu sederhana? Anda mengambil objek, mengkloningnya, mengubah apa pun yang Anda butuhkan, dan hei presto - Anda mendapatkan sendiri objek baru.
Sekarang Anda mungkin bertanya, "Bagaimana ini sederhana? Setiap kali saya ingin membuat lingkaran baru saya harus mengkloning
circle
dan secara manual menetapkan radius". Nah solusinya adalah menggunakan fungsi untuk melakukan angkat berat untuk Anda:Bahkan Anda bisa menggabungkan semua ini menjadi satu objek literal sebagai berikut:
Warisan Prototypal dalam JavaScript
Jika Anda perhatikan dalam program di atas,
create
fungsi ini membuat kloncircle
, menetapkan yang baruradius
untuk itu dan kemudian mengembalikannya. Inilah yang dilakukan konstruktor dalam JavaScript:Pola konstruktor dalam JavaScript adalah pola prototipe terbalik. Alih-alih membuat objek Anda membuat konstruktor. Kata
new
kunci mengikatthis
pointer di dalam konstruktor ke klon dariprototype
konstruktor.Kedengarannya membingungkan? Itu karena pola konstruktor dalam JavaScript tidak perlu memperumit banyak hal. Inilah yang sulit dipahami oleh kebanyakan programmer.
Alih-alih memikirkan objek yang diwarisi dari objek lain, mereka memikirkan konstruktor yang diwarisi dari konstruktor lain dan kemudian menjadi sangat bingung.
Ada banyak alasan lain mengapa pola konstruktor dalam JavaScript harus dihindari. Anda dapat membacanya di posting blog saya di sini: Konstruktor vs Prototipe
Jadi apa manfaat warisan prototipal dari warisan klasik? Mari kita kembali ke argumen yang paling umum, dan menjelaskan alasannya .
1. Warisan prototipe sederhana
CMS menyatakan dalam jawabannya:
Mari kita pertimbangkan apa yang baru saja kita lakukan. Kami menciptakan objek
circle
yang memiliki radius5
. Lalu kami mengkloningnya dan memberi klon jari-jari10
.Karenanya kita hanya perlu dua hal untuk membuat warisan warisan prototipe berfungsi:
Object.create
.).Sebaliknya warisan klasik jauh lebih rumit. Dalam warisan klasik, Anda memiliki:
Anda mendapatkan idenya. Intinya adalah bahwa pewarisan prototypal lebih mudah dipahami, lebih mudah diterapkan, dan lebih mudah dipikirkan.
Seperti yang dikatakan Steve Yegge di posting blog klasiknya " Portrait of a N00b ":
Dalam arti yang sama, kelas hanyalah meta-data. Kelas tidak sepenuhnya diwajibkan untuk warisan. Namun beberapa orang (biasanya n00b) merasa kelas lebih nyaman untuk dikerjakan. Ini memberi mereka rasa aman yang salah.
Seperti yang saya katakan sebelumnya, kelas memberi orang rasa aman yang salah. Misalnya Anda mendapatkan terlalu banyak
NullPointerException
di Jawa bahkan ketika kode Anda terbaca dengan sempurna. Saya menemukan warisan klasik biasanya menghalangi pemrograman, tapi mungkin itu hanya Java. Python memiliki sistem warisan klasik yang menakjubkan.2. Warisan Prototypal Kuat
Sebagian besar programmer yang berasal dari latar belakang klasik berpendapat bahwa warisan klasik lebih kuat daripada warisan prototypal karena memiliki:
Klaim ini salah. Kita sudah tahu bahwa JavaScript mendukung variabel pribadi melalui penutupan , tetapi bagaimana dengan multiple inheritance? Objek dalam JavaScript hanya memiliki satu prototipe.
Yang benar adalah bahwa warisan mendukung prototip mewarisi dari beberapa prototipe. Warisan prototipe hanya berarti satu objek mewarisi dari objek lain. Sebenarnya ada dua cara untuk mengimplementasikan warisan prototypal :
Ya JavaScript hanya mengizinkan objek untuk didelegasikan ke satu objek lainnya. Namun itu memungkinkan Anda untuk menyalin properti dari sejumlah objek yang berubah-ubah. Misalnya
_.extend
tidak hanya ini.Tentu saja banyak programmer tidak menganggap ini sebagai warisan yang benar karena
instanceof
danisPrototypeOf
mengatakan sebaliknya. Namun ini dapat dengan mudah diperbaiki dengan menyimpan berbagai prototipe pada setiap objek yang mewarisi dari prototipe melalui gabungan:Karenanya, warisan purwarupa sama kuatnya dengan warisan klasik. Sebenarnya itu jauh lebih kuat daripada warisan klasik karena dalam warisan prototypal Anda dapat memilih properti mana yang akan disalin dan properti mana yang akan dihilangkan dari prototipe yang berbeda.
Dalam warisan klasik tidak mungkin (atau setidaknya sangat sulit) untuk memilih properti mana yang ingin Anda warisi. Mereka menggunakan kelas dasar virtual dan antarmuka untuk memecahkan masalah berlian .
Namun dalam JavaScript, Anda kemungkinan besar tidak akan pernah mendengar masalah berlian karena Anda dapat mengontrol properti mana yang ingin Anda warisi dan dari prototipe mana.
3. Warisan Prototypal Kurang Redundan
Poin ini sedikit lebih sulit untuk dijelaskan karena warisan klasik tidak selalu mengarah pada kode yang lebih berlebihan. Sebenarnya pewarisan, baik klasik atau prototypal, digunakan untuk mengurangi redundansi dalam kode.
Salah satu argumen bisa jadi sebagian besar bahasa pemrograman dengan warisan klasik diketik secara statis dan mengharuskan pengguna untuk secara eksplisit mendeklarasikan jenis (tidak seperti Haskell yang memiliki pengetikan statis implisit). Karenanya ini mengarah pada kode yang lebih verbose.
Java terkenal karena perilaku ini. Saya ingat dengan jelas Bob Nystrom menyebutkan anekdot berikut dalam posting blognya tentang Pratt Parsers :
Sekali lagi, saya pikir itu hanya karena Java sangat menyebalkan.
Salah satu argumen yang valid adalah bahwa tidak semua bahasa yang memiliki warisan klasik mendukung pewarisan berganda. Sekali lagi Jawa muncul di benak. Ya Java memiliki antarmuka, tetapi itu tidak cukup. Terkadang Anda benar-benar membutuhkan pewarisan berganda.
Karena pewarisan prototypal memungkinkan pewarisan berganda, kode yang membutuhkan pewarisan berganda tidak terlalu berlebihan jika ditulis menggunakan pewarisan prototypal daripada dalam bahasa yang memiliki warisan klasik tetapi tidak memiliki pewarisan berganda.
4. Warisan Prototypal Dinamis
Salah satu keuntungan terpenting dari pewarisan prototypal adalah Anda dapat menambahkan properti baru ke prototipe setelah dibuat. Ini memungkinkan Anda untuk menambahkan metode baru ke prototipe yang akan secara otomatis tersedia untuk semua objek yang didelegasikan ke prototipe itu.
Ini tidak mungkin dalam warisan klasik karena sekali kelas dibuat Anda tidak dapat memodifikasinya saat runtime. Ini mungkin satu-satunya keuntungan terbesar dari warisan purwarupa dibandingkan warisan klasik, dan seharusnya berada di puncak. Namun saya suka menyimpan yang terbaik untuk akhir.
Kesimpulan
Masalah pewarisan prototipe. Sangat penting untuk mendidik programmer JavaScript tentang mengapa meninggalkan pola konstruktor pewarisan prototypal demi pola prototipe pewarisan prototypal.
Kita perlu mulai mengajar JavaScript dengan benar dan itu berarti menunjukkan kepada programmer baru cara menulis kode menggunakan pola prototypal alih-alih pola konstruktor.
Tidak hanya akan lebih mudah untuk menjelaskan warisan prototypal menggunakan pola prototypal, tetapi juga akan membuat programmer lebih baik.
Jika Anda menyukai jawaban ini maka Anda juga harus membaca posting blog saya di " Mengapa Prototypal Inheritance Matters ". Percayalah, Anda tidak akan kecewa.
sumber
Object.create
sedang membuat objek baru dengan prototipe yang ditentukan. Pilihan kata-kata Anda memberi kesan bahwa prototipe akan dikloning.Izinkan saya untuk benar-benar menjawab pertanyaan sebaris.
Warisan prototipe memiliki sifat-sifat berikut:
Namun memiliki kelemahan sebagai berikut:
Saya pikir Anda dapat membaca yang tersirat di atas dan muncul dengan kelebihan dan kekurangan yang sesuai dari skema kelas / objek tradisional. Ada, tentu saja, lebih banyak di setiap area sehingga saya akan menyerahkan sisanya kepada orang lain untuk menjawab.
sumber
IMO manfaat utama pewarisan prototypal adalah kesederhanaannya.
Sifat prototipal bahasa dapat membingungkan orang-orang yang terlatih secara klasik , tetapi ternyata ini adalah konsep yang benar - benar sederhana dan kuat, pewarisan diferensial .
Anda tidak perlu membuat klasifikasi , kode Anda lebih kecil, kurang redundan, objek diwarisi dari objek lain yang lebih umum.
Jika Anda berpikir secara prototipikal, Anda akan segera menyadari bahwa Anda tidak perlu kelas ...
Warisan prototipe akan jauh lebih populer dalam waktu dekat, spesifikasi ECMAScript 5th Edition memperkenalkan
Object.create
metode ini, yang memungkinkan Anda untuk menghasilkan instance objek baru yang diwarisi dari objek lain dengan cara yang sangat sederhana:Versi standar baru ini sedang diimplementasikan oleh semua vendor browser, dan saya pikir kita akan mulai melihat lebih banyak warisan purwarupa purwarupa ...
sumber
Sebenarnya tidak banyak yang bisa dipilih di antara kedua metode ini. Gagasan dasar untuk dipahami adalah bahwa ketika mesin JavaScript diberikan properti objek untuk dibaca, pertama-tama memeriksa instance dan jika properti itu hilang, ia memeriksa rantai prototipe. Berikut adalah contoh yang menunjukkan perbedaan antara prototypal dan klasik:
Prototipal
Klasik dengan metode instance (Tidak efisien karena setiap instance menyimpan properti itu sendiri)
Klasik yang efisien
Seperti yang Anda lihat, karena dimungkinkan untuk memanipulasi prototipe "kelas" yang dinyatakan dalam gaya klasik, benar-benar tidak ada manfaatnya menggunakan pewarisan prototipal. Ini adalah bagian dari metode klasik.
sumber
Pengembangan Web: Warisan Prototip vs. Warisan Klasik
http://chamnapchhorn.blogspot.com/2009/05/prototypal-inheritance-vs-classical.html
Warisan prototipe klasik Vs - Stack Overflow
Warisan prototipe klasik Vs
sumber