1 Warisan dalam JavaScript ialah topik yang sangat kompleks, jauh lebih kompleks daripada warisan dalam mana-mana bahasa berorientasikan objek lain. Dalam kebanyakan bahasa berorientasikan objek lain, mewarisi daripada kelas hanya memerlukan penggunaan kata kunci. Tidak seperti mereka, untuk mencapai tujuan mewarisi ahli awam dalam JavaScript, satu siri langkah perlu diambil. Lebih-lebih lagi, JavaScript ialah salah satu daripada beberapa bahasa yang menggunakan warisan prototaip. Terima kasih kepada fleksibiliti bahasa, anda boleh menggunakan sama ada warisan berasaskan kelas standard atau warisan prototaip yang lebih halus.
2. Mengapa pewarisan diperlukan?Secara umumnya, apabila mereka bentuk kelas, kami berharap dapat mengurangkan kod berulang dan cuba melemahkan gandingan antara objek. Menggunakan warisan memenuhi keperluan prinsip reka bentuk sebelumnya. Dengan mekanisme ini, anda boleh mereka bentuk berdasarkan kelas sedia ada dan memanfaatkan kaedah yang telah mereka miliki, dan lebih mudah untuk mengubah suai reka bentuk. Katakan anda memerlukan beberapa kelas untuk mempunyai kaedah toString() yang mengeluarkan struktur kelas dengan cara tertentu Sudah tentu, anda boleh menyalin dan menampal kod yang mentakrifkan kaedah toString() ke dalam setiap kelas, tetapi jika anda melakukan ini, Bila-bila masa. anda perlu mengubah cara kaedah ini berfungsi, anda perlu mengulang pengubahsuaian yang sama dalam setiap kelas. Sebaliknya, jika anda menyediakan kelas ToStringProvider dan kemudian membiarkan kelas tersebut mewarisi kelas ini, maka kaedah toString hanya perlu diisytiharkan di satu tempat.
Memiliki satu kelas mewarisi daripada kelas lain boleh membawa kepada gandingan yang kuat antara kedua-duanya, iaitu satu kelas bergantung pada pelaksanaan dalaman kelas yang lain. Kami akan membincangkan beberapa teknik yang boleh membantu mengelakkan masalah ini, termasuk menggunakan kelas dopan untuk menyediakan kaedah untuk kelas lain.
3. Warisan berasaskan kelasLihat kod di bawah:
<script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; } Person.prototype.say = function () { console.log(this.name + " , " + this.age); } function Student(no) { this.no = no; } /** * Student的prototype指向Person的对象 */</span> Student.prototype = new Person(); var stu1 = new Student("0001"); stu1.name = '张三'; stu1.age = '11'; console.log(stu1.no); stu1.say(); </script>
Zhang San, 11
Anda boleh melihat bahawa Pelajar telah berjaya menyepadukan Orang dan mempunyai kaedah katakan Orang Kod teras sebenarnya ialah Pelajar.prototaip = orang baru();. Berikut ialah gambar rajah untuk menggambarkan prinsip:
Tuding Student.prototype kepada Person() baru, dan _proto_ Person baru menunjuk ke Prototype Person ini melengkapkan keseluruhan warisan.
Tetapi terdapat masalah dengan pendekatan ini:
Masalah 1: Apabila kelas induk mempunyai pembolehubah jenis rujukan, data tidak konsisten Seterusnya, kami menambah atribut hobi kepada Orang, yang jenisnya ialah tatasusunan.
<script type="text/javascript"> /** * 存在问题 * 1、无法在Student的构造方法中传递参数用于父类的构造方法 * 2、对于引用类型变量,造成数据不一致 */ function Person(name, age) { this.name = name; this.age = age; this.hobbies = [] ; } Person.prototype.say = function () { console.log(this.name + " , " + this.age +" , " +this.hobbies); } function Student(no) { this.no = no; } Student.prototype = new Person(); var stu1 = new Student("0001"); stu1.name = '张三'; stu1.age = '11'; stu1.hobbies.push("soccer"); stu1.say(); var stu2 = new Student("0002"); stu2.name = '李四'; stu2.age = '12'; stu2.hobbies.push("girl"); stu2.say(); </script>
Zhang San, 11, bola sepak
Li Si , 12 , bola sepak, perempuan
Dapat dilihat bahawa hobi John Doe sepatutnya perempuan sahaja, tetapi kod di atas membenarkan semua objek berkongsi atribut hobi.
Masih ada masalah dengan kaedah pewarisan di atas:
Soalan 2: Dalam pembina Pelajar, Pelajar baharu("00001", "Zhang San", 12) tidak boleh digunakan untuk mencipta objek dan memulakan nama dan umur Atribut mesti diberikan stu.name, stu.age Untuk menyelesaikan masalah di atas, ubah suai kod di atas:
<script type="text/javascript"> function Person(name, age) { this.name = name; this.age = age; this.hobbies = []; } Person.prototype.say = function () { console.log(this.name + " , " + this.age +" , " + this.hobbies); } function Student(name, age, no) { /** * 使用call方法,第一个参数为上下文; * 有点类似Java中的super(name,age)的感觉 */ Person.call(this, name, age); this.no = no; } Student.prototype = new Person(); var stu1 = new Student("0001","张三",11); stu1.hobbies.push("soccer"); stu1.say(); var stu2 = new Student("0002","李四",12); stu2.hobbies.push("cangjin"); stu2.hobbies.push("basketball"); stu2.say(); </script>
0001, Zhang San, bola sepak
0002, Li Si, cangjin, bola keranjang
Menggunakan Person.call(ini,nama,umur) dalam pembina Pelajar terasa seperti super(nama,umur) [parameter pertama panggilan ialah konteks] dan berjaya menyelesaikan rujukan Masalah perkongsian atribut diselesaikan dengan sempurna.
<script type="text/javascript"> /** * 基于原型链的集成中都是对象 * 存在问题: * 1、对于引用类型变量,造成数据不一致 */ var Person = { name: "人", age: 0, hobbies: [], say: function () { console.log(this.name + " , " + this.age + " , " + this.hobbies); } } ; var Student = clone(Person); Student.no =""; Student.sayHello = function() { console.log(this.name +"hello ") ; } var stu1 = clone(Student); stu1.name = "zhangsan"; stu1.age = 12; stu1.hobbies.push("Java"); stu1.say(); var stu2 = clone(Student); stu2.name = "lisi"; stu2.age = 13; stu2.hobbies.push("Javascript"); stu2.say(); /** * 返回一个prototype执行obj的一个对象 * @param obj * @returns {F} */ function clone(obj) { var F = function () { }; F.prototype = obj; return new F(); } </script>
zhangsan, 12, Java
lisi, 13, Java,Javascript
Dapat dilihat bahawa terdapat juga masalah atribut rujukan yang tidak konsisten, dan keseluruhan operasi adalah berdasarkan objek, yang tidak memberi orang perasaan yang baik Prinsip ini dijelaskan di bawah melalui rajah:
Objek secara berterusan mengembalikan objek baharu melalui fungsi klon, dan prototaip melaksanakan objek masuk Keseluruhan proses pewarisan sebenarnya _proto_ sentiasa menunjuk untuk membentuk rantai, jadi ia dipanggil rantai prototaip.
Baiklah, kami telah memperkenalkannya daripada dua kaedah penyepaduan js, yang terbaik adalah melalui pewarisan kelas, yang agak stabil.
Di atas adalah pengenalan kepada perkara-perkara yang berkaitan tentang pewarisan, saya harap ia dapat membantu pembelajaran semua orang.