Rumah >hujung hadapan web >Soal Jawab bahagian hadapan >Apakah kegunaan warisan javascript?
Fungsi warisan JavaScript: 1. Anda boleh mencipta kejadian baharu tanpa memanggil pembina "kelas induk" 2. Mengubah suai prototaip "kelas induk" boleh mengubah suai semua kejadian yang dibuat secara dinamik; Anda boleh mengubah suai prototaip objek secara dinamik.
Persekitaran pengendalian tutorial ini: sistem Windows 7, versi JavaScript 1.8.5, komputer Dell G3.
JavaScript ialah model pembangunan berorientasikan objek berdasarkan objek, berfungsi sebagai model dan prototaip sebagai warisan.
Peranan warisan JavaScript:
1 Anda boleh mencipta contoh baharu tanpa memanggil pembina "kelas induk"
2 , Ubah suai prototaip "kelas induk" untuk mengubah suai secara dinamik semua kejadian yang dicipta 3. Anda boleh mengubah suai prototaip objek secara dinamik, yang bermaksud ibu bapa boleh mengubahnyaYang berikut memperkenalkan definisi kaedah jenis JavaScript, dan corak biasa untuk melaksanakan warisan.Membina prototaip
Terdapat dua masalah dalam menggunakan prototaip secara langsung untuk mereka bentuk warisan kelas. Memandangkan pembina diisytiharkan terlebih dahulu dan sifat prototaip ditakrifkan selepas struktur kelas diisytiharkan, parameter tidak boleh dihantar secara dinamik kepada prototaip melalui pembina. Dengan cara ini, objek yang di instantiated semuanya kelihatan sama dan tidak mempunyai personaliti. Untuk menukar nilai sifat prototaip, semua kejadian akan terjejas. Apabila nilai atribut prototaip ialah data jenis rujukan, jika nilai atribut diubah suai dalam satu contoh objek, ia akan menjejaskan semua kejadian. Contoh 1Cuma tentukan jenis Buku dan kemudian nyatakannya.function Book () {}; //声明构造函数 Book.prototype.o = {x : 1, y : 2}; //构造函数的原型属性o是一个对象 var book1 = new Book (); //实例化对象book1 var book2 = new Book (); //实例化对象book2 console.log(book1.o.x); //返回1 console.log(book2.o.x); //返回1 book2.o.x = 3; //修改实例化对象book2中的属性x的值 console.log(book1.o.x); //返回3 console.log(book2.o.x); //返回3Memandangkan atribut prototaip o ialah nilai rujukan, nilai atribut o semua kejadian adalah rujukan kepada objek yang sama Setelah nilai o berubah, ia akan mempengaruhi semua kejadian. Prototaip pembinaan ialah corak reka bentuk hibrid yang dilahirkan untuk menyelesaikan corak prototaip Ia mencampurkan corak pembina dan corak prototaip untuk mengelakkan masalah di atas. Kaedah pelaksanaan: Untuk atribut prototaip yang mungkin mempengaruhi satu sama lain dan atribut yang ingin melepasi parameter secara dinamik, ia boleh direka bentuk secara bebas menggunakan corak pembina. Untuk kaedah atau atribut yang tidak memerlukan reka bentuk individu dan mempunyai ciri umum, anda boleh menggunakan corak prototaip untuk mereka bentuk. Contoh 2Ikuti prinsip reka bentuk di atas, reka dua sifat ke dalam corak pembina, dan kaedah reka bentuk ialah corak prototaip.
function Book (title, pages) { //构造函数模式设计 this.title = title; this.pages = pages; } Book.prototype.what = function () { //原型模式设计 console.log(this.title + this.pages); }; var book1 = new Book("JavaScript 程序设计", 160); var book2 = new Book("C语言程序设计", 240); console.log(book1.title); console.log(book2.title);Corak Prototaip Terbina ialah standard yang disyorkan untuk menentukan kelas dalam ECMAScript. Secara amnya disyorkan untuk menggunakan corak pembina untuk menentukan semua sifat dan corak prototaip untuk menentukan semua kaedah. Dengan cara ini semua kaedah dibuat sekali sahaja, dan setiap contoh boleh menetapkan nilai harta seperti yang diperlukan. Ini juga merupakan corak reka bentuk yang paling banyak digunakan.
Prototaip dinamik
Menurut prinsip reka bentuk berorientasikan objek, semua ahli sesuatu jenis hendaklah dirangkumkan dalam struktur kelas. Contohnya:function Book (title, pages) { //构造函数模式设计 this.title = title; this.pages = pages; Book.prototype.what = function () { //原型模式设计,位于类的内部 console.log(this.title + this.pages); }; }Tetapi setiap kali ia dijalankan, kaedah prototaip yang terkandung dalam kelas Buku akan dibuat berulang kali, menghasilkan sejumlah besar kaedah prototaip dan membazirkan sumber sistem. Anda boleh menggunakan jika untuk menentukan sama ada kaedah prototaip wujud. Jika ia wujud, kaedah itu tidak akan dibuat.
function Book (title, pages) { this.title = title; this.pages = pages; if (typeof Book.isLock == "undefined") { //创建原型方法的锁,如果不存在则创建 Book.prototype.what = function () { console.log(this.title + this.pages); }; Book.isLock = true; //创建原型方法后,把锁锁上,避免重复创建 } } var book1 = new Book("JavaScript 程序设计", 160); var book2 = new Book("C语言程序设计", 240); console.log(book1.title); console.log(book2.title);jenis ungkapan Book.isLock boleh mengesan jenis nilai atribut Jika ia mengembalikan rentetan yang tidak ditentukan, nilai atribut tidak wujud, menunjukkan bahawa tiada kaedah prototaip telah dibuat dan membenarkan penciptaan. kaedah prototaip Tetapan Nilai atribut ini adalah benar, supaya tidak perlu berulang kali mencipta kaedah prototaip. Nama kelas Buku digunakan di sini dan bukannya ini kerana prototaip kepunyaan kelas itu sendiri, bukan contoh objek. Mod prototaip dinamik dan mod prototaip yang dibina adalah setara dalam prestasi Pengguna boleh memilih secara bebas, tetapi mod prototaip yang dibina lebih banyak digunakan.
Corak Kilang
Corak kilang ialah kaedah paling asas untuk menentukan jenis dan juga merupakan corak pembangunan yang paling biasa digunakan dalam JavaScript. Ia hanya merangkum instantiasi objek dalam fungsi, dan kemudian memanggil fungsi untuk mencapai pengeluaran pantas dan kumpulan objek contoh. Contoh 1Contoh berikut mereka bentuk jenis Kereta: ia mengandungi tiga sifat: warna kereta, bilangan roda pemanduan dan penggunaan bahan api setiap 100 kilometer, dan juga mentakrifkan kaedah untuk memaparkan warna kereta.function Car (color, drive, oil) { //汽车类 var _car = new Object(); //临时对象 _car.color = color; //初始化颜色 _car.drive = drive; //初始化驱动轮数 _car.oil = oil; //初始化百公里油耗 _car.showColor = function () { //方法,提示汽车颜色 console.log(this.color); }; return _car; //返回实例 } var car1 = Car("red", 4, 8); var car2 = Car("blue", 2, 6); car1.showColor(); //输出“red” car2.showColor(); //输出“blue”Kod di atas ialah jenis corak kilang yang ringkas Dengan menggunakan kelas Kereta, anda boleh membuat berbilang contoh kereta dengan pantas, tetapi atributnya berbeza. bilangan roda pemanduan, dan Penggunaan bahan api setiap kilometer. Contoh 2Dalam jenis, kaedah ialah tingkah laku atau operasi yang boleh menyelesaikan tugas tertentu berdasarkan parameter permulaan dan mempunyai ciri-ciri biasa. Oleh itu, anda boleh mempertimbangkan untuk meletakkan kaedah di luar fungsi Car() untuk mengelak daripada mencipta fungsi setiap kali ia dijalankan dan biarkan setiap kejadian berkongsi fungsi yang sama.
function showColor () { //公共方法,提示汽车颜色 console.log(this.color); }; function Car (color, drive, oil) { //汽车类 var _car = new Object(); //临时对象 _car.color = color; //初始化颜色 _car.drive = drive; //初始化驱动轮数 _car.oil = oil; //初始化百公里油耗 _car.showColor = showColor; //引用外部函数 return _car; //返回实例 }Dalam kod yang ditulis semula di atas, fungsi showColor() ditakrifkan sebelum fungsi Car(). Inside Car(), dengan merujuk fungsi showColor() luaran, kami mengelak daripada mencipta fungsi baharu setiap kali ia diwujudkan. Secara fungsional, ini menyelesaikan masalah berulang kali mencipta fungsi tetapi secara semantik, fungsi itu kurang seperti kaedah objek.
Warisan kelas
Kaedah reka bentuk warisan kelas: panggil pembina kelas induk dalam subkelas.在 JavaScript 中实现类继承,需要注意以下 3 个技术问题。
在子类中,使用 apply 调用父类,把子类构造函数的参数传递给父类父类构造函数。让子类继承父类的私有属性,即 Parent.apply(this, arguments); 代码行。
在父类和子类之间建立原型链,即 Sub.prototype = new Parent(); 代码行。通过这种方式保证父类和子类是原型链上的上下级关系,即子类的 prototype 指向父类的一个实例。
恢复子类的原型对象的构造函数,即 Sub.prototype.constructor=Sub;语句行。当改动 prototype 原型时,就会破坏原来的 constructor 指针,所以必须重置 constructor。
示例1
下面示例演示了一个三重继承的案例,包括基类、父类和子类,它们逐级继承。
//基类Base function Base (x) { //构造函数Base this.get = function () { //私有方法,获取参数值 return x; } } Base.prototype.has = function () { //原型方法,判断get()方法返回值是否为0 return ! (this.get() == 0); } //父类Parent function Parent () { //构造函数Parent var a = []; //私有数组a a = Array.apply(a, arguments); //把参数转换为数组 Base.call(this, a.length); //调用Base类,并把参数数组长度传递给它 this.add = function () { //私有方法,把参数数组补加到数组a中并返回 return a.push.apply(a, arguments) } this.geta = function () { //私有方法,返回数组a return a; } } Parent.prototype = new Base(); //设置Parent原型为Base的实例,建立原型链 Parent.prototype.constructor = Parent; //恢复Parent类原型对象的构造器 Parent.prototype.str = function (){ //原型方法,把数组转换为字符串并返回 return this.geta().toString(); } //子类Sub function Sub () { //构造函数 Parent.apply(this, arguments); //调用Parent类,并把参数数组长度传递给它 this.sort = function () { //私有方法,以字符顺序对数组进行排序 var a = this.geta(); //获取数组的值 a.sort.apply(a, arguments); //调用数组排序方法 sort()对数组进行排序 } } Sub.prototype = new Parent(); //设置Sub原型为Parent实例,建立原型链 Sub.prototype.constructor = Sub; //恢复Sub类原型对象的构造器 //父类Parent的实例继承类Base的成员 var parent = new Parent (1, 2, 3, 4); //实例化Parent类 console.log(parent.get()); //返回4,调用Base类的方法get() console.log(parent.has()); //返回true,调用Base类的方法has() //子类Sub的实例继承类Parent和类Base的成员 var sub = new Sub (30, 10, 20, 40); //实例化Sub类 sub.add(6, 5); //调用Parent类方法add(),补加数组 console.log(sub.geta()); //返回数组30,10,20,40,6,5 sub.sort(); //排序数组 console.log(sub.geta()); //返回数组10,20,30,40,5,6 console.log(sub.get()); //返回4,调用Base类的方法get() console.log(sub.has()); //返回true,调用Base类的方法has() console.log(sub.str()); //返回10,20,30,40,5,6
【设计思路】
设计子类 Sub 继承父类 Parent,而父类 Parent 又继承基类 Base。Base、Parent、Sub 三个类之间的继承关系是通过在子类中调用的构造函数来维护的。
例如,在 Sub 类中,Parent.apply(this, arguments); 能够在子类中调用父类,并把子类的参数传递给父类,从而使子类拥有父类的所有属性。
同理,在父类中,Base.call(this, a.length); 把父类的参数长度作为值传递给基类,并进行调用,从而实现父类拥有基类的所有成员。
从继承关系上看,父类继承了基类的私有方法 get(),为了确保能够继承基类的原型方法,还需要为它们建立原型链,从而实现原型对象的继承关系,方法是添加语句行 Parent.prototype=new Base();。
同理,在子类中添加语句 Sub.prototype=new Parent();,这样通过原型链就可以把基类、父类和子类串连在一起,从而实现子类能够继承父类属性,还可以继承基类的属性。
示例2
下面尝试把类继承模式封装起来,以便规范代码应用。
function extend (Sub, Sup) { //类继承封装函数 var F = function () {}; //定义一个空函数 F.prototype = Sup.prototype; //设置空函数的原型为父类的原型 Sub.prototype = new F (); //实例化空函数,并把父类原型引用传给给子类 Sub.prototype.constructor = Sub; //恢复子类原型的构造器为子类自身 Sub.sup = Sup.prototype; //在子类定义一个私有属性存储父类原型 //检测父类原型构造器是否为自身 if (Sup.prototype.constructor == Object.prototype.constructor) { Sup.prototype.constructor = Sup; //类继承封装函数 } }
【操作步骤】
1) 定义一个封装函数。设计入口为子类和父类对象,函数功能是子类能够继承父类的所有原型成员,不涉及出口。
function extend (Sub, Sup) { //类继承封装函数 //其中参数Sub表示子类,Sup表示父类 }
2) 在函数体内,首先定义一个空函数 F,用来实现功能中转。设计它的原型为父类的原型,然后把空函数的实例传递给子类的原型,这样就避免了直接实例化父类可能带来的系统负荷。因为在实际开发中,父类的规模可能会很大,如果实例化,会占用大量内存。
3) 恢复子类原型的构造器为子类自己。同时,检测父类原型构造器是否与 Object 的原型构造器发生耦合。如果是,则恢复它的构造器为父类自身。
下面定义两个类,尝试把它们绑定为继承关系。
function A (x) { //构造函数A this.x = x; //私有属性x this.get = function () { //私有方法get() return this.x; } } A.prototype.add = function () { //原型方法add() return this.x + this.x; } A.prototype.mul = function () { //原型方法mul() return this.x * this.x; } function B (x) { //构造函数B A.call (this.x); //在函数体内调用构造函数A,实现内部数据绑定 } extend (B, A); //调用封装函数,把A和B的原型捆绑在一起 var f = new B (5); //实例化类B console.log(f.get()); //继承类A的方法get(),返回5 console.log(f.add()); //继承类A的方法add(),返回10 console.log(f.mul()); //继承类A的方法mul(),返回25
在函数类封装函数中,有这么一句 Sub.sup=Sup.prototype;,在上面代码中没有被利用,那么它有什么作用呢?为了解答这个问题,先看下面的代码。
extend (B, A); B.prototype.add = function () { //为B类定义一个原型方法 return this.x + "" + this.x; }
上面的代码是在调用封装函数之后,再为 B 类定义了一个原型方法,该方法名与基类中原型方法 add() 同名,但是功能不同。如果此时测试程序,会发现子类 B 定义的原型方法 add() 将会覆盖父类 A 的原型方法 add()。
console.log(f.add()); //返回字符串55,而不是数值10
如果在 B 类的原型方法 add() 中调用父类的原型方法 add(),避免代码耦合现象发生。
B.prototype.add = function () { //定义子类B的原型方法add() return B.sup.add.call(this); //在函数内部调用父类方法add() }
【相关推荐:javascript学习教程】
Atas ialah kandungan terperinci Apakah kegunaan warisan javascript?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!