Rumah >hujung hadapan web >tutorial js >Penjelasan terperinci tentang kemahiran JavaScript inheritance_javascript berorientasikan objek
1. Mekanisme pewarisan objek
Contoh ini menggunakan UML untuk menerangkan mekanisme pewarisan dengan baik.
Cara paling mudah untuk menggambarkan mekanisme pewarisan adalah dengan menggunakan contoh klasik bentuk geometri. Sebenarnya, hanya terdapat dua jenis bentuk geometri, elips (yang berbentuk bulat) dan poligon (yang mempunyai bilangan sisi tertentu). Bulatan ialah sejenis elips yang hanya mempunyai satu fokus. Segitiga, segi empat tepat dan pentagon ialah semua jenis poligon yang mempunyai bilangan sisi yang berbeza-beza. Segi empat sama ialah sejenis segi empat tepat dengan semua sisi sama panjang. Ini membentuk hubungan pewarisan yang sempurna dan menerangkan mekanisme pewarisan berorientasikan objek dengan baik.
Dalam contoh ini, bentuknya ialah kelas asas elips dan poligon (biasanya kita juga boleh memanggilnya kelas induk, dan semua kelas mewarisi daripadanya). Ellips mempunyai fokus, yang menunjukkan bilangan fokus elips mempunyai. Bulatan mewarisi daripada elips, jadi bulatan ialah subkelas elips dan elips ialah kelas super bulatan. Begitu juga, segi tiga, segi empat tepat dan pentagon adalah semua subkelas poligon, yang merupakan superclass mereka. Akhirnya, segi empat sama mewarisi segi empat tepat.
Adalah lebih baik untuk menggunakan gambar rajah untuk menerangkan hubungan warisan ini, di mana UML (Unified Modelling Language) masuk. Salah satu kegunaan utama UML adalah untuk mewakili secara visual hubungan objek kompleks seperti warisan. Rajah berikut ialah rajah UML yang menerangkan hubungan antara bentuk dan subkelasnya:
Dalam UML, setiap kotak mewakili kelas, diterangkan mengikut nama kelas. Segmen garis di bahagian atas segi tiga, segi empat tepat dan pentagon bersatu untuk menunjuk kepada bentuk, menunjukkan bahawa kelas ini mewarisi daripada bentuk. Begitu juga, anak panah yang menunjuk dari segi empat sama ke segi empat tepat menggambarkan hubungan warisan antara mereka.
2. Pelaksanaan mekanisme pewarisan ECMAScript
Untuk melaksanakan mekanisme pewarisan dengan ECMAScript, anda boleh bermula dengan kelas asas yang anda ingin warisi. Semua kelas yang ditentukan oleh pembangun boleh berfungsi sebagai kelas asas. Atas sebab keselamatan, kelas asli dan hos tidak boleh berfungsi sebagai kelas asas Ini menghalang akses awam kepada kod peringkat penyemak imbas yang boleh digunakan untuk serangan berniat jahat.
Selepas memilih kelas asas, anda boleh mencipta subkelasnya. Terpulang kepada anda sama ada hendak menggunakan kelas asas atau tidak. Kadangkala, anda mungkin ingin mencipta kelas asas yang tidak boleh digunakan secara langsung, tetapi hanya digunakan untuk menyediakan fungsi biasa kepada subkelas. Dalam kes ini, kelas asas dianggap sebagai kelas abstrak. Walaupun ECMAScript tidak mentakrifkan kelas abstrak dengan ketat seperti bahasa lain, ia kadangkala mencipta kelas yang tidak dibenarkan untuk digunakan. Biasanya, kami memanggil kelas ini sebagai kelas abstrak.
Subkelas yang dicipta akan mewarisi semua sifat dan kaedah superclass, termasuk pelaksanaan pembina dan kaedah. Ingat, semua sifat dan kaedah adalah awam, jadi subkelas boleh mengakses kaedah ini secara langsung. Subkelas juga boleh menambah sifat dan kaedah baharu yang tidak ditemui dalam superclass, atau mereka boleh mengatasi sifat dan kaedah superclass. Memandangkan JS bukan bahasa berorientasikan objek ortodoks, beberapa kata nama juga perlu diubah.
3. Kaedah pewarisan ECMAScript
Dalam bahasa ECMAScript, kelas yang diwarisi (kelas asas) dipanggil supertype, dan subclass (atau kelas terbitan) dipanggil subjenis. Seperti ciri lain, ECMAScript melaksanakan pewarisan dalam lebih daripada satu cara. Ini kerana mekanisme pewarisan dalam JavaScript tidak dinyatakan secara eksplisit, tetapi dilaksanakan melalui tiruan. Ini bermakna tidak semua butiran pewarisan dikendalikan sepenuhnya oleh jurubahasa. Sebagai pembangun, anda mempunyai hak untuk menentukan kaedah pewarisan yang paling sesuai untuk anda. Berikut ialah beberapa kaedah pewarisan khusus untuk anda.
(1) Kaedah rantai prototaip
Bentuk warisan ini pada asalnya digunakan untuk rantai prototaip dalam ECMAScript. Catatan blog sebelum ini telah memperkenalkan kaedah prototaip untuk mencipta objek. Rantaian prototaip memanjangkan pendekatan ini untuk melaksanakan mekanisme pewarisan dengan cara yang menarik. Objek prototaip ialah templat, dan objek yang akan dijadikan instantiated adalah berdasarkan templat ini. Secara ringkasnya, sebarang sifat dan kaedah objek prototaip dihantar kepada semua kejadian kelas itu. Rantaian prototaip menggunakan fungsi ini untuk melaksanakan mekanisme pewarisan. Mari lihat contoh:
function A() {//超类型A中必须没有参数 this.color = "red"; this.showColor = function () { return this.color; }; }; function B() {//子类型B this.name = "John"; this.showName = function () { return this.name; }; }; B.prototype = new A();//子类型B继承了超类型A,通过原型,形成链条 var a = new A(); var b = new B(); document.write(a.showColor());//输出:blue document.write(b.showColor());//输出:red document.write(b.showName());//输出:John
Dalam rantaian prototaip, pengendali instanceof juga beroperasi dengan cara yang unik. Untuk semua contoh B, instanceof mengembalikan benar untuk kedua-dua A dan B. Ini ialah alat yang sangat berguna dalam dunia ECMAScript yang ditaip lemah, tetapi ia tidak boleh digunakan apabila menggunakan penyamaran objek. Contohnya:
var b = new B(); document.write(b instanceof A);//输出:true document.write(b instanceof B);//输出:true
使用原型链方式实现了继承,但是这种方式无法共享和子类型给超类型传递参数。我们可以借用构造函数方式(也就是对像冒充)的方式来解决这两个问题。
(2)对象冒充方式
对象冒充方式的其原理如下:构造函数使用this关键字给所有属性和方法赋值(即采用对象声明的构造函数方式)。因为构造函数只是一个函数,所以可使A构造函数成为B的方法,然后调用它。B就会收到A的构造函数中定义的属性和方法。例如,用下面的方式改写上面的例子创建对象A和B:
call()方法
function A(Color) {//创建超类型A this.color = Color; this.showColor = function () { return this.color; }; }; function B(Color,Name) {//创建子类型B A.call(this, Color);//对象冒充,给超类型传参 this.name = Name;//新添加的属性 this.showName = }; var a = new A("blue"); var b = new B("red", "John"); document.write(a.showColor());//输出:blue document.write(b.showColor());//输出:red document.write(b.showName());//输出:John
apply()方法
和上面call()方法唯一的区别就是在子类型B中的代码:
A.call(this,arguments);//对象冒充,给超类型传参
当然,只有超类型中的参数顺序与子类型中的参数顺序完全一致时才可以传递参数对象。如果不是,就必须创建一个单独的数组,按照正确的顺序放置参数。
使用对象冒充方式虽然解决了共享和传参的问题,但是没有原型,复用就更不可能了,所以我们组合上述的两种方式,即原型链方式和对象冒充的方式实现JS的继承。
(3)混合方式
这种继承方式使用构造函数定义类,并非使用任何原型。对象冒充的主要问题是必须使用构造函数方式,这不是最好的选择。不过如果使用原型链,就无法使用带参数的构造函数了。开发者如何选择呢?答案很简单,两者都用。由于这种混合方式使用了原型链,所以instanceof运算符仍能正确运行。
在上一篇文章,创建对象的最好方式是用构造函数定义属性,用原型定义方法。这种方式同样适用于继承机制,用对象冒充继承构造函数的属性,用原型链继承prototype对象的方法。用这两种方式重写前面的例子,代码如下:
function A(Color) { this.color = Color; }; A.prototype.showColor = function () { return this.color; }; function B(Color, Name) { A.call(this, Color);//对象冒充 this.name = Name; }; B.prototype = new A();//使用原型链继承 B.prototype.showName = function () { return this.name; }; var a = new A("blue"); var b = new B("red", "John"); document.write(a.showColor());//输出:blue document.write(b.showColor());//输出:red document.write(b.showName());//输出:John
继承的方式和创建对象的方式有一定的联系,推荐使用的继承方式还时原型链和对象冒充的混合方式。使用这种混合方式可以避免一些不必要的问题。
看这篇文章的时候,必须看一下前面的创建对象的方式:详解JavaScript基于面向对象之创建对象(1)和详解JavaScript基于面向对象之创建对象(2)。
以上就是本文的全部内容,希望对大家的学习有所帮助。