Manfaat warisan purba dibandingkan klasik?

271

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.

Pierreten
sumber
kemungkinan rangkap dari Memahami warisan prototipe dalam JavaScript
John Slegers

Jawaban:

560

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):

  1. Itu mudah.
  2. Sangat kuat.
  3. Ini mengarah ke kode yang lebih kecil, kurang redundan.
  4. Ini dinamis dan karenanya lebih baik untuk bahasa dinamis.

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:

  1. Pola prototipe pewarisan prototypal.
  2. Pola konstruktor 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):

Dan kami mendorongnya sebagai saudara kecil ke Jawa, karena bahasa pelengkap seperti Visual Basic adalah untuk C ++ dalam keluarga bahasa Microsoft pada saat itu.

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 :

Tipuan ini dimaksudkan untuk membuat bahasa tampak lebih akrab bagi programmer yang terlatih secara klasik, tetapi gagal melakukannya, seperti yang dapat kita lihat dari pendapat yang sangat rendah yang dimiliki programmer Java tentang JavaScript. Pola konstruktor JavaScript tidak menarik bagi orang banyak klasik. Itu juga mengaburkan sifat prototipal sejati JavaScript. Akibatnya, ada sangat sedikit programmer yang tahu cara menggunakan bahasa secara efektif.

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:

  1. Buat objek baru.
  2. Klon objek yang sudah ada dan perluas.

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:

var circle = {
    radius: 5
};

Kita dapat menghitung luas dan keliling lingkaran dari jari-jarinya:

circle.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

circle.circumference = function () {
    return 2 * Math.PI * this.radius;
};

Sekarang saya ingin membuat lingkaran jari-jari lain 10. Salah satu cara untuk melakukan ini adalah:

var circle2 = {
    radius: 10,
    area: circle.area,
    circumference: circle.circumference
};

Namun JavaScript menyediakan cara yang lebih baik - delegasi . The Object.createFungsi ini digunakan untuk melakukan hal ini:

var circle2 = Object.create(circle);
circle2.radius = 10;

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 circledan secara manual menetapkan radius". Nah solusinya adalah menggunakan fungsi untuk melakukan angkat berat untuk Anda:

function createCircle(radius) {
    var newCircle = Object.create(circle);
    newCircle.radius = radius;
    return newCircle;
}

var circle2 = createCircle(10);

Bahkan Anda bisa menggabungkan semua ini menjadi satu objek literal sebagai berikut:

var circle = {
    radius: 5,
    create: function (radius) {
        var circle = Object.create(this);
        circle.radius = radius;
        return circle;
    },
    area: function () {
        var radius = this.radius;
        return Math.PI * radius * radius;
    },
    circumference: function () {
        return 2 * Math.PI * this.radius;
    }
};

var circle2 = circle.create(10);

Warisan Prototypal dalam JavaScript

Jika Anda perhatikan dalam program di atas, createfungsi ini membuat klon circle, menetapkan yang baru radiusuntuk itu dan kemudian mengembalikannya. Inilah yang dilakukan konstruktor dalam JavaScript:

function Circle(radius) {
    this.radius = radius;
}

Circle.prototype.area = function () {
    var radius = this.radius;
    return Math.PI * radius * radius;
};

Circle.prototype.circumference = function () {         
    return 2 * Math.PI * this.radius;
};

var circle = new Circle(5);
var circle2 = new Circle(10);

Pola konstruktor dalam JavaScript adalah pola prototipe terbalik. Alih-alih membuat objek Anda membuat konstruktor. Kata newkunci mengikat thispointer di dalam konstruktor ke klon dari prototypekonstruktor.

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:

Menurut pendapat saya, manfaat utama pewarisan prototypal adalah kesederhanaannya.

Mari kita pertimbangkan apa yang baru saja kita lakukan. Kami menciptakan objek circleyang memiliki radius 5. Lalu kami mengkloningnya dan memberi klon jari-jari 10.

Karenanya kita hanya perlu dua hal untuk membuat warisan warisan prototipe berfungsi:

  1. Cara untuk membuat objek baru (misalnya objek literal).
  2. Cara untuk memperluas objek yang ada (mis Object.create.).

Sebaliknya warisan klasik jauh lebih rumit. Dalam warisan klasik, Anda memiliki:

  1. Kelas.
  2. Obyek.
  3. Antarmuka.
  4. Kelas Abstrak.
  5. Kelas Akhir.
  6. Kelas Dasar Virtual.
  7. Konstruktor.
  8. Destructors.

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 ":

Metadata adalah segala jenis deskripsi atau model dari sesuatu yang lain. Komentar dalam kode Anda hanyalah deskripsi bahasa alami dari perhitungan. Apa yang membuat metadata meta-data adalah bahwa itu tidak sepenuhnya diperlukan. Jika saya memiliki anjing dengan beberapa dokumen silsilah, dan saya kehilangan dokumennya, saya masih memiliki anjing yang valid.

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.

Kita juga tahu bahwa tipe statis hanyalah metadata. Mereka adalah jenis komentar khusus yang ditargetkan untuk dua jenis pembaca: programmer dan kompiler. Tipe statis menceritakan kisah tentang perhitungan, mungkin untuk membantu kedua kelompok pembaca memahami maksud dari program. Tetapi tipe statis dapat dibuang saat runtime, karena pada akhirnya mereka hanya komentar bergaya. Mereka seperti dokumen silsilah: mungkin membuat tipe kepribadian tertentu yang tidak aman lebih bahagia tentang anjing mereka, tetapi anjing itu tentu saja tidak peduli.

Seperti yang saya katakan sebelumnya, kelas memberi orang rasa aman yang salah. Misalnya Anda mendapatkan terlalu banyak NullPointerExceptiondi 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:

  1. Variabel pribadi.
  2. Warisan berganda.

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 :

  1. Delegasi atau Warisan Diferensial
  2. Kloning atau Warisan Konsatenatif

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 _.extendtidak hanya ini.

Tentu saja banyak programmer tidak menganggap ini sebagai warisan yang benar karena instanceofdan isPrototypeOfmengatakan sebaliknya. Namun ini dapat dengan mudah diperbaiki dengan menyimpan berbagai prototipe pada setiap objek yang mewarisi dari prototipe melalui gabungan:

function copyOf(object, prototype) {
    var prototypes = object.prototypes;
    var prototypeOf = Object.isPrototypeOf;
    return prototypes.indexOf(prototype) >= 0 ||
        prototypes.some(prototypeOf, prototype);
}

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 :

Anda harus menyukai tingkat birokrasi Java "tandatangani dalam empat kali lipat" di sini.

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.

Aadit M Shah
sumber
33
Sementara saya mengerti dari mana Anda berasal, dan saya setuju bahwa warisan prototypal sangat berguna, saya pikir dengan membuat asumsi "warisan prototypal lebih baik daripada warisan klasik" Anda sudah ditakdirkan untuk gagal. Untuk memberi Anda beberapa perspektif, perpustakaan saya jTypes adalah perpustakaan warisan klasik untuk JavaScript. Jadi menjadi seorang pria yang meluangkan waktu untuk membuat itu, saya akan tetap duduk di sini dan mengatakan warisan prototypal itu luar biasa dan sangat berguna. Tapi itu hanyalah satu alat di antara banyak yang dimiliki seorang programmer. Masih banyak kerugian untuk warisan prototypal juga.
redline
7
Saya sepenuhnya setuju dengan apa yang Anda katakan. Saya merasa bahwa terlalu banyak programmer menolak JavaScript karena kurangnya warisan klasik, atau mencela itu sebagai bahasa yang sederhana dan bodoh. Ini sebenarnya konsep yang sangat kuat, saya setuju, dan banyak programmer harus menerimanya dan mempelajarinya. Dengan itu, saya juga merasa ada sejumlah besar pengembang dalam JavaScript yang menentang segala bentuk warisan klasik yang semuanya berada dalam JavaScript, ketika mereka benar-benar tidak memiliki dasar untuk argumen mereka sama sekali. Keduanya sama-sama kuat dalam hak mereka sendiri, dan sama-sama bermanfaat juga.
redline
9
Nah itu pendapat Anda, tapi saya akan terus tidak setuju, dan saya pikir semakin populernya hal-hal seperti CoffeeScript dan TypeScript menunjukkan bahwa ada komunitas besar pengembang yang ingin memanfaatkan fungsi ini saat yang tepat. Seperti yang Anda katakan, ES6 menambahkan gula sintaksis, tetapi masih tidak menawarkan perpanjangan jTypes. Sebagai catatan, saya bukan orang yang bertanggung jawab atas downvote Anda. Sementara saya tidak setuju dengan Anda, saya tidak merasa itu merupakan jawaban yang buruk. Kamu sangat teliti.
redline
25
Anda sering menggunakan kata klon , yang memang salah. Object.createsedang membuat objek baru dengan prototipe yang ditentukan. Pilihan kata-kata Anda memberi kesan bahwa prototipe akan dikloning.
Pavel Horal
7
@Adit: benar-benar tidak perlu bersikap defensif. Jawaban Anda sangat terperinci dan layak mendapatkan suara. Saya tidak menyarankan bahwa "tertaut" harus menjadi pengganti drop-in untuk "klon", tetapi itu lebih tepat menggambarkan hubungan antara suatu objek dan prototipe yang diwarisi dari, apakah Anda menegaskan definisi Anda sendiri dari istilah "klon" " atau tidak. Ubah atau jangan ubah, itu sepenuhnya pilihan Anda.
Andy E
42

Izinkan saya untuk benar-benar menjawab pertanyaan sebaris.

Warisan prototipe memiliki sifat-sifat berikut:

  1. Ini lebih cocok untuk bahasa dinamis karena pewarisannya sama dinamisnya dengan lingkungannya. (Penerapan JavaScript harus jelas di sini.) Ini memungkinkan Anda untuk melakukan hal-hal dengan cepat seperti menyesuaikan kelas tanpa perlu banyak kode infrastruktur. .
  2. Lebih mudah untuk mengimplementasikan skema objek prototyping daripada skema dikotomi kelas / objek klasik.
  3. Ini menghilangkan kebutuhan untuk tepi tajam yang kompleks di sekitar model objek seperti "metaclasses" (Saya tidak pernah metaclass saya suka ... maaf!) ​​Atau "nilai eigen" atau sejenisnya.

Namun memiliki kelemahan sebagai berikut:

  1. Ketik memeriksa bahasa prototipe bukan tidak mungkin, tetapi sangat, sangat sulit. Kebanyakan "pengecekan tipe" dari bahasa-bahasa prototipikal adalah pemeriksaan gaya-murni "duck typing". Ini tidak cocok untuk semua lingkungan.
  2. Sama sulitnya untuk melakukan hal-hal seperti mengoptimalkan metode pengiriman dengan analisis statis (atau, seringkali, bahkan dinamis!). Itu bisa (saya tekankan: bisa ) menjadi sangat tidak efisien dengan sangat mudah.
  3. Demikian pula, pembuatan objek dapat (dan biasanya) jauh lebih lambat dalam bahasa prototyping daripada dalam skema dikotomi kelas / objek yang lebih konvensional.

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.

HANYA PENDAPAT SAYA yang benar
sumber
1
Hei lihat, jawaban singkat yang tidak fanboy. Benar-benar berharap ini adalah jawaban teratas untuk pertanyaan itu.
siliconrockstar
Kami memiliki kompiler Just-in-time Dinamis hari ini yang dapat mengkompilasi kode ketika kode sedang berjalan membuat potongan-potongan kode yang berbeda untuk setiap bagian. JavaScript sebenarnya lebih cepat daripada Ruby atau Python yang menggunakan kelas klasik karena ini bahkan jika Anda menggunakan prototipe karena banyak pekerjaan yang telah dilakukan untuk mengoptimalkannya.
aoeu256
28

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.createmetode ini, yang memungkinkan Anda untuk menghasilkan instance objek baru yang diwarisi dari objek lain dengan cara yang sangat sederhana:

var obj = Object.create(baseInstance);

Versi standar baru ini sedang diimplementasikan oleh semua vendor browser, dan saya pikir kita akan mulai melihat lebih banyak warisan purwarupa purwarupa ...

CMS
sumber
11
"kode kamu lebih kecil, tidak berlebihan ...", mengapa? Saya telah melihat tautan wikipedia untuk "diferensial inheritance" dan tidak ada yang mendukung pernyataan ini. Mengapa warisan klasik menghasilkan kode yang lebih besar, lebih redundan?
Noel Abrahams
4
Persis, saya setuju dengan Noel. Warisan prototipe hanyalah salah satu cara untuk menyelesaikan pekerjaan, tetapi itu tidak menjadikannya jalan yang benar. Alat yang berbeda akan bekerja dengan cara yang berbeda untuk pekerjaan yang berbeda. Warisan prototipe memiliki tempatnya. Ini adalah konsep yang sangat kuat dan sederhana. Dengan itu dikatakan, kurangnya dukungan untuk enkapsulasi dan polimorfisme yang benar membuat JavaScript pada kerugian yang signifikan. Metodologi ini telah ada jauh lebih lama daripada JavaScript, dan mereka sehat di kepala mereka. Jadi berpikir prototypal adalah "lebih baik" hanyalah mentalitas yang salah sama sekali.
redline
1
Anda dapat mensimulasikan pewarisan berbasis kelas menggunakan pewarisan berbasis prototipe, tetapi tidak sebaliknya. Itu mungkin argumen yang bagus. Saya juga melihat enkapsulasi lebih sebagai konvensi daripada fitur bahasa (biasanya Anda dapat memecah enkapsulasi melalui refleksi). Mengenai polimorfisme - semua yang Anda dapatkan tidak harus menulis beberapa kondisi "jika" sederhana ketika memeriksa argumen metode (dan sedikit kecepatan jika metode target diselesaikan saat kompilasi). Tidak ada kerugian JavaScript nyata di sini.
Pavel Horal
Prototipe itu mengagumkan, IMO. Saya berpikir untuk membuat bahasa fungsional seperti Haskell ... tetapi alih-alih membuat abstraksi saya akan mendasarkan semuanya pada prototipe. Alih-alih menyamaratakan jumlah, dan faktorial untuk "melipat" Anda harus prototipe fungsi penjumlahan dan mengganti + dengan * dan 0 dengan 1 untuk membuat produk. Saya akan menjelaskan "Monads" sebagai prototipe yang menggantikan "lalu" dari janji / panggilan balik dengan flatMap menjadi sinonim dari "lalu". Saya pikir prototipe dapat membantu membawa pemrograman fungsional kepada massa.
aoeu256
11

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

var single = { status: "Single" },
    princeWilliam = Object.create(single),
    cliffRichard = Object.create(single);

console.log(Object.keys(princeWilliam).length); // 0
console.log(Object.keys(cliffRichard).length); // 0

// Marriage event occurs
princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1 (New instance property)
console.log(Object.keys(cliffRichard).length); // 0 (Still refers to prototype)

Klasik dengan metode instance (Tidak efisien karena setiap instance menyimpan properti itu sendiri)

function Single() {
    this.status = "Single";
}

var princeWilliam = new Single(),
    cliffRichard = new Single();

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 1

Klasik yang efisien

function Single() {
}

Single.prototype.status = "Single";

var princeWilliam = new Single(),
    cliffRichard = new Single();

princeWilliam.status = "Married";

console.log(Object.keys(princeWilliam).length); // 1
console.log(Object.keys(cliffRichard).length); // 0
console.log(cliffRichard.status); // "Single"

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.

Noel Abrahams
sumber
2
Melihat jawaban dan sumber lain tentang topik ini, jawaban Anda tampaknya menyatakan: "Warisan prototipe adalah bagian dari gula sintaksis yang ditambahkan ke JavaScript untuk memungkinkan penampilan warisan klasik". OP tampaknya bertanya tentang manfaat warisan prototipal di JS dibandingkan warisan klasik dalam bahasa lain daripada membandingkan teknik instantiasi dalam JavaScript.
A Fader Darkly
2

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

rapi
sumber
20
Saya pikir lebih baik untuk meringkas isi tautan daripada menempelkan tautan (sesuatu yang biasa saya lakukan sendiri), kecuali jika itu adalah tautan SO lainnya. Ini karena tautan / situs turun dan Anda kehilangan respons terhadap pertanyaan, dan itu berpotensi memengaruhi hasil pencarian.
James Westgate
Tautan ke-1 tidak menjawab pertanyaan mengapa pewarisan prototypal? Itu hanya menggambarkannya.
Viebel