偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

淺析JavaScript繼承方式

開(kāi)發(fā) 前端
面向?qū)ο蟮恼Z(yǔ)言多數(shù)都支持繼承,繼承最重要的優(yōu)點(diǎn)就是代碼復(fù)用,從而構(gòu)建大型軟件系統(tǒng)。如果一個(gè)類(lèi)能夠重用另一個(gè)類(lèi)的屬性和或方法,就稱(chēng)之為繼承。從這個(gè)角度來(lái)看看JavaScript的繼承方式。

前段時(shí)間溫故了下JavaScript 的寫(xiě)類(lèi)方式,從這篇開(kāi)始我們看看JavaScript 的繼承方式。

面向?qū)ο蟮恼Z(yǔ)言多數(shù)都支持繼承,繼承最重要的優(yōu)點(diǎn)就是代碼復(fù)用,從而構(gòu)建大型軟件系統(tǒng)。如果一個(gè)類(lèi)能夠重用另一個(gè)類(lèi)的屬性和或方法,就稱(chēng)之為繼承。從這個(gè)角度來(lái)看看JS的繼承方式。JS中繼承方式與寫(xiě)類(lèi)方式息息相關(guān)。不同的寫(xiě)類(lèi)方式造成不同的繼承方式。各種流行JavaScript庫(kù)繼承方式也各不相同。從最簡(jiǎn)單的復(fù)用開(kāi)始。

1、構(gòu)造函數(shù)方式寫(xiě)類(lèi),通過(guò)方法調(diào)用復(fù)制父類(lèi)屬性/字段到子類(lèi) 實(shí)現(xiàn)繼承

這里父類(lèi),子類(lèi)都采用構(gòu)造函數(shù)方式寫(xiě),不用原型。子類(lèi)調(diào)用父類(lèi)函數(shù)來(lái)復(fù)制父類(lèi)的屬性。

  1. /**  
  2.  * 父類(lèi)Polygon:多邊形  
  3.  * @param {Object} sides  
  4.  */ 
  5. function Polygon(sides) {  
  6.     this.sides = sides;  
  7.     this.setSides = function(s) {this.sides=s;}  
  8. }  
  9.  
  10. /**  
  11.  * 子類(lèi)Triangle:三角形  
  12.  */ 
  13. function Triangle() {  
  14.     this.tempfun = Polygon;//父類(lèi)引用賦值給子類(lèi)的一個(gè)屬性tempfun  
  15.     this.tempfun(3);//調(diào)用  
  16.     delete this.tempfun;//刪除該屬性  
  17.     this.getArea = function(){};  
  18. }  
  19.  
  20. //new個(gè)對(duì)象   
  21. var tri = new Triangle();  
  22. console.log(tri.sides);//繼承的屬性  
  23. console.log(tri.setSides);//繼承的方法  
  24. console.log(tri.getArea);//自有的方法  
  25.  
  26. //缺點(diǎn)是對(duì)于Triangle的實(shí)例對(duì)象用instanceof為父類(lèi)Polygon時(shí)是false  
  27. console.log(tri instanceof Triangle);//true  
  28. console.log(tri instanceof Polygon);//false 

因?yàn)?JavaScript中具名函數(shù)的多種調(diào)用方式 ,子類(lèi)還可以有以下的多種實(shí)現(xiàn)方式。只是在子類(lèi)中調(diào)用父類(lèi)方法不同而已。

  1. function Triangle() {  
  2.     Polygon.call(this,3); //call方式調(diào)用父類(lèi)  
  3.     this.getArea = function(){};      
  4. }  
  5. function Triangle() {  
  6.     Polygon.apply(this,[3]); //apply方式調(diào)用父類(lèi)  
  7.     this.getArea = function(){};  
  8. }  
  9. function Triangle() {  
  10.     var temp = new Polygon(3); //new方式調(diào)用父類(lèi)  
  11.     for(atr in temp) { //全部復(fù)制給子類(lèi)  
  12.         this[atr] = temp[atr];  
  13.     }     
  14.     this.getArea = function(){};  

這種方式的缺點(diǎn)是子類(lèi)的實(shí)例對(duì)象用instanceof檢查父類(lèi)時(shí)總是false。這與java中繼承"is a "的關(guān)系是違背的。

2、原型方式寫(xiě)類(lèi),原型方式繼承

core JS自身的對(duì)象系統(tǒng)就是采用原型方式(prototype based)繼承的?;蛘哒f(shuō)core JS沒(méi)有采用常見(jiàn)的類(lèi)繼承(class based)系統(tǒng),而是使用原型繼承來(lái)實(shí)現(xiàn)自己的對(duì)象系統(tǒng)。工作中我們也可以用原型方式來(lái)實(shí)現(xiàn)繼承,代碼復(fù)用以構(gòu)建自己的功能模塊。

  1. /**  
  2.  * 父類(lèi)Polygon:多邊形  
  3.  *   
  4.  */ 
  5. function Polygon() {}  
  6. Polygon.prototype.sides = 0;  
  7. Polygon.prototype.setSides = function(s) {this.sides=s;}  
  8.  
  9. /**  
  10.  * 子類(lèi)Triangle:三角形  
  11.  */ 
  12. function Triangle() {}  
  13. Triangle.prototype = new Polygon(); //這是原型繼承關(guān)鍵的一句  
  14. Triangle.prototype.getArea = function(){}  
  15.  
  16. //new個(gè)對(duì)象  
  17. var tri = new Triangle();  
  18. console.log(tri.sides);//繼承的屬性  
  19. console.log(tri.setSides);//繼承的方法  
  20. console.log(tri.getArea);//自有方法  
  21.  
  22. //instanceof測(cè)試  
  23. console.log(tri instanceof Triangle);//true,表明該對(duì)象是三角形  
  24. console.log(tri instanceof Polygon);//true,表明三角形也是多邊形 

雖然從輸出可以看出子類(lèi)繼承了父類(lèi)Polygon的屬性sides和方法setSides,但sides是0,怎么會(huì)是三角形呢。還得調(diào)用下tri.setSides(3)使之成為三角形。這樣似乎很不方便。不能傳參數(shù),即是原型方式的缺點(diǎn)。優(yōu)點(diǎn)是正確的維護(hù)了"is a"的關(guān)系。

3、組合構(gòu)造函數(shù)/原型方式寫(xiě)類(lèi),采用前面種方式繼承

這種方式父類(lèi),子類(lèi)的屬性都掛在構(gòu)造函數(shù)里,方法都掛在原型上。

  1. /**  
  2.  * 父類(lèi)Polygon:多邊形  
  3.  */ 
  4. function Polygon(sides) {  
  5.     this.sides = sides;  
  6. }  
  7. Polygon.prototype.setSides = function(s) {this.sides=s;}  
  8.  
  9. /**  
  10.  * Triangle 三角形  
  11.  * @param {Object} base 底  
  12.  * @param {Object} height 高  
  13.  */ 
  14. function Triangle(base,height) {  
  15.     Polygon.call(this,3);//復(fù)制父類(lèi)屬性給自己  
  16.     this.base = base;  
  17.     this.height = height;  
  18. }  
  19. Triangle.prototype = new Polygon();//復(fù)制父類(lèi)方法給自己  
  20.  
  21. Triangle.prototype.getArea = function(){ //***定義自己的方法  
  22.     return this.base*this.height/2;  
  23. }  
  24.  
  25. //new個(gè)對(duì)象  
  26. var tri = new Triangle(12,4);  
  27. console.log(tri.sides);//繼承的屬性  
  28. console.log(tri.setSides);//繼承的方法  
  29. console.log(tri.base);//自有屬性  
  30. console.log(tri.height);//自有屬性  
  31. console.log(tri.getArea);//自有方法  
  32.  
  33. //instanceof測(cè)試,表明正確的維護(hù)了"is a"的關(guān)系  
  34. console.log(tri instanceof Triangle);//true,表明該對(duì)象是三角形  
  35. console.log(tri instanceof Polygon);//true,表明三角形也是多邊形 

#p#

這篇開(kāi)始寫(xiě)幾個(gè)工具函數(shù)實(shí)現(xiàn)類(lèi)的擴(kuò)展。每個(gè)工具函數(shù)都是針對(duì)特定的寫(xiě)類(lèi)方式(習(xí)慣)。這篇按照構(gòu)造函數(shù)方式寫(xiě)類(lèi):屬性(字段)和方法都掛在this上。以下分別提供了個(gè)類(lèi),分別作為父類(lèi)和子類(lèi)。

  1. //  父類(lèi)Person  
  2. function Person(nationality) {  
  3.     this.nationality = nationality;  
  4.     this.setNationality = function(n) {this.nationality=n;};  
  5.     this.getNationality = function() {return this.nationality;};  
  6. }  
  7.  
  8. // 類(lèi)Man  
  9. function Man(name) {  
  10.     this.name = name;  
  11.     this.setName = function(n){this.name=n;};  
  12.     this.getName = function(){return this.name;};  

繼承工具函數(shù)一

  1. /**  
  2.  * @param {Function} subCls 子類(lèi)  
  3.  * @param {Function} superCls 父類(lèi)  
  4.  * @param {Object} param 父類(lèi)構(gòu)造參數(shù)  
  5.  */ 
  6. function extend(subCls,superCls,param) {  
  7.     superCls.call(subCls.prototype,param);  

使用如下

  1. extend(Man,Person,'China');  
  2. var m = new Man('jack');  
  3. console.log(m.nationality);//China  
  4. console.log(m.setNationality('Japan'));  
  5. console.log(m.getNationality('Japan'));//Japan 

輸出可以看到Man繼承了Person的屬性及所有方法。這種繼承方式于java的很不一樣哦,

  1. class Animal {  
  2.     int legs;     
  3.     Animal(int l) {  
  4.         legs = l;  
  5.     }  
  6.     int getLegs() {  
  7.         return legs;  
  8.     }  
  9. }  
  10. public class Person extends Animal{  
  11.     //屬性(字段)  
  12.     String name;      
  13.     //構(gòu)造方法(函數(shù))  
  14.     Person(int legs, String name) {  
  15.         super(legs);//調(diào)用父類(lèi)構(gòu)造器  
  16.         this.name = name;  
  17.     }     
  18.     //方法  
  19.     String getName() {  
  20.         return this.name;  
  21.     }  
  22.     public static void main(String[] args) {  
  23.           
  24.         Person p = new Person(2,"jack");          
  25.         System.out.println(p.legs);  
  26.     }  

Java中,子類(lèi)Person在自身構(gòu)造方法中調(diào)用父類(lèi)構(gòu)造方法super(legs),創(chuàng)建對(duì)象的時(shí)候直接將父類(lèi)構(gòu)造參數(shù)legs:2傳進(jìn)去,不僅僅只傳自己的name:jack。上面JavaScript繼承是在extend時(shí)傳父類(lèi)構(gòu)造參數(shù)(extend函數(shù)的第三個(gè)參數(shù)),而不是在new Man時(shí)將父類(lèi)構(gòu)造參數(shù)傳過(guò)去。好,模擬Java來(lái)實(shí)現(xiàn)下extend,這里巧妙的在子類(lèi)上暫存了父類(lèi)引用。

繼承工具函數(shù)二

  1. /**  
  2.  * @param {Function} subCls  
  3.  * @param {Function} superCls  
  4.  */ 
  5. function extend(subCls,superCls) {    
  6.     subCls.supr = superCls;  
  7. }  

還是以Person為父類(lèi),來(lái)實(shí)現(xiàn)子類(lèi)Woman

  1. function Woman(nationality,name) {  
  2.     Woman.supr.call(this,nationality);//和java有點(diǎn)類(lèi)似哦,在子類(lèi)中調(diào)用父類(lèi)構(gòu)造器  
  3.     this.name = name;  
  4.     this.setName = function(n){this.name=n;};  
  5.     this.getName = function(){return this.name;};  
  6. }<br>extend(Woman,Person);<br> 

***,創(chuàng)建對(duì)象的方式和java也類(lèi)似,即new的時(shí)候同時(shí)將父類(lèi)構(gòu)造參數(shù)(nationality:Japan)傳進(jìn)去。

  1. var w = new Woman('Japan','lily');  
  2. console.log(w.nationality);//Japan  
  3. w.setNationality('U.S.A');  
  4. console.log(w.getNationality());//U.S.A 

繼承工具函數(shù)三

  1. /**  
  2.  * @param {Function} subCls  
  3.  * @param {Function} superCls  
  4.  */ 
  5. function extend(subCls,superCls) {  
  6.     subCls.prototype = new superCls();    

父類(lèi),按原型方式寫(xiě),即屬性和方法都掛在原型上。

  1. /**  
  2.  *  父類(lèi)Person  
  3.  */ 
  4. function Person(){}  
  5. Person.prototype.nationality = 'China';  
  6. Person.prototype.getNationality = function() {return this.nationality;}  
  7. Person.prototype.setNationality = function(n) { this.nationality = n;} 

子類(lèi)繼承與父類(lèi)

  1. function Man() {}  
  2. extend(Man,Person); 

繼承父類(lèi)的屬性和方法后,再添加子類(lèi)自有屬性,方法

  1. Man.prototype.name = 'jack';  
  2. Man.prototype.getName = function() { return this.name;}  
  3. Man.prototype.setName = function(n) { this.name=n;} 

測(cè)試如下,

  1. var m = new Man();  
  2. console.log(m);  
  3. console.log(m instanceof Person); 

可以看到這種寫(xiě)類(lèi)方式,繼承方式完全采用原型機(jī)制。

#p#

繼承工具函數(shù)四

這種方式是目前比較流行的,51ditu網(wǎng)站的開(kāi)發(fā)就是按照這種模式的。

  1. /**  
  2.  * @param {Function} subCls 子類(lèi)  
  3.  * @param {Function} superCls 父類(lèi)  
  4.  */ 
  5. function extend(subCls,superCls) {    
  6.     //暫存子類(lèi)原型  
  7.     var sbp = subCls.prototype;  
  8.     //重寫(xiě)子類(lèi)原型--原型繼承  
  9.     subCls.prototype = new superCls();  
  10.     //重寫(xiě)后一定要將constructor指回subCls  
  11.     subCls.prototype.constructor = subCls;  
  12.     //還原子類(lèi)原型  
  13.     for(var atr in sbp) {  
  14.         subCls.prototype[atr] = sbp[atr];  
  15.     }  
  16.     //暫存父類(lèi)    
  17.     subCls.supr = superCls;  

按 構(gòu)造函數(shù)+原型 方式寫(xiě)類(lèi),即屬性掛在this上,方法掛在prototype上。

  1. /**  
  2.  *  父類(lèi)Person  
  3.  */ 
  4. function Person(nationality){  
  5.     this.nationality = nationality;  
  6. }  
  7. Person.prototype.getNationality = function() {return this.nationality;}  
  8. Person.prototype.setNationality = function(n) { this.nationality = n;}  
  9.  
  10. /**  
  11.  *  子類(lèi)Man  
  12.  */ 
  13. function Man(nationality,name) {  
  14.     Man.supr.call(this,nationality); //很重要的一句,調(diào)用父類(lèi)構(gòu)造器  
  15.     this.name = name;  
  16. }  
  17. Man.prototype.getName = function() {return this.name;}  
  18. Man.prototype.setName = function(n) {this.name=n;} 

注意子類(lèi)Man中要顯示的調(diào)用父類(lèi)構(gòu)造器已完成父類(lèi)的屬性/字段拷貝。

extend調(diào)用,創(chuàng)建Man的實(shí)例

  1. extend(Man,Person);  
  2. var m = new Man('USA','jack');  
  3. console.log(m);  
  4. m.setName('lily');  
  5. console.log(m.name); 

繼承工具函數(shù)五

  1. /**  
  2.  * @param {String} className  
  3.  * @param {String/Function} superClass  
  4.  * @param {Function} classImp  
  5.  */ 
  6. function $class(className, superClass, classImp){  
  7.     if(superClass === "") superClass = Object;  
  8.     var clazz = function(){  
  9.         return function(){  
  10.             if(typeof this.init == "function"){  
  11.                 this.init.apply(this, arguments);  
  12.             }  
  13.         };  
  14.     }();  
  15.     var p = clazz.prototype = new superClass();  
  16.     var _super = superClass.prototype;  
  17.     window[className] = clazz;  
  18.     classImp.apply(p, [_super]);  

定義父類(lèi)Person

  1. /**  
  2.  * 父類(lèi) Person  
  3.  */ 
  4. $class('Person','',function(){  
  5.     this.init = function(name){  
  6.         this.name = name;  
  7.     };  
  8.     this.getName = function(){  
  9.         return this.name;  
  10.     };  
  11.     this.setName = function(name){  
  12.         this.name = name;  
  13.     }  
  14. }); 

子類(lèi)Man

  1. /**  
  2.  * 子類(lèi) Man  
  3.  */ 
  4. $class('Man', Person, function(supr){  
  5.     this.init = function(name, age){  
  6.         supr.init.apply(this,[name]); // 該句很重要  
  7.         this.age = age;  
  8.     };  
  9.     this.getAge = function(){  
  10.         return this.age;  
  11.     };  
  12.     this.setAge = function(age){  
  13.         this.age = age;  
  14.     };  
  15. });  
  16. var m = new Man('Jack',25);  
  17. console.log(m.name); // Jack  
  18. console.log(m.age); // 25 

從輸出看可以看到子類(lèi)Man的確繼承了父類(lèi)的屬性和方法。

原文鏈接:http://www.cnblogs.com/snandy/archive/2011/03/09/1977804.html

【編輯推薦】

  1. 如何編寫(xiě)高質(zhì)量的Javascript代碼
  2. 淺析JavaScript的寫(xiě)類(lèi)方式
  3. JavaScript跨域總結(jié)與解決辦法
  4. JavaScript版幾種常見(jiàn)排序算法分享
  5. 10個(gè)令人驚奇的HTML5和JavaScript效果
責(zé)任編輯:陳貽新 來(lái)源: snandy的博客
相關(guān)推薦

2011-03-07 09:41:10

JavaScript

2017-06-26 10:35:58

前端JavaScript繼承方式

2011-03-08 09:15:04

JavaScript

2009-09-25 14:12:16

Hibernate繼承

2020-04-28 10:05:33

JavaScript繼承前端

2010-01-21 13:48:30

C++基類(lèi)

2011-08-31 14:48:33

JavaScript

2012-02-14 09:45:02

JavaScript

2010-09-28 14:12:50

Javascript

2017-07-21 09:40:35

Python類(lèi)、繼承和多態(tài)

2009-08-13 18:15:06

C#繼承構(gòu)造函數(shù)

2011-08-24 13:56:27

JavaScript

2021-12-04 11:17:32

Javascript繼承編程

2009-06-17 14:55:26

Hibernate數(shù)據(jù)

2021-07-27 22:56:00

JavaScript編程開(kāi)發(fā)

2009-07-14 11:34:42

MyEclipse斷點(diǎn)JavaScript

2009-09-07 05:24:22

C#窗體繼承

2010-02-06 17:39:52

C++ strtok

2009-06-25 17:24:06

Hibernate主鍵

2009-07-08 17:42:26

this屬性
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)