自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

淺析JavaScript繼承方式

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

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

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

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

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

  1. /**  
  2.  * 父類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.  * 子類Triangle:三角形  
  12.  */ 
  13. function Triangle() {  
  14.     this.tempfun = Polygon;//父類引用賦值給子類的一個(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為父類Polygon時(shí)是false  
  27. console.log(tri instanceof Triangle);//true  
  28. console.log(tri instanceof Polygon);//false 

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

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

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

2、原型方式寫類,原型方式繼承

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

  1. /**  
  2.  * 父類Polygon:多邊形  
  3.  *   
  4.  */ 
  5. function Polygon() {}  
  6. Polygon.prototype.sides = 0;  
  7. Polygon.prototype.setSides = function(s) {this.sides=s;}  
  8.  
  9. /**  
  10.  * 子類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測試  
  23. console.log(tri instanceof Triangle);//true,表明該對(duì)象是三角形  
  24. console.log(tri instanceof Polygon);//true,表明三角形也是多邊形 

雖然從輸出可以看出子類繼承了父類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ù)/原型方式寫類,采用前面種方式繼承

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

  1. /**  
  2.  * 父類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ù)制父類屬性給自己  
  16.     this.base = base;  
  17.     this.height = height;  
  18. }  
  19. Triangle.prototype = new Polygon();//復(fù)制父類方法給自己  
  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測試,表明正確的維護(hù)了"is a"的關(guān)系  
  34. console.log(tri instanceof Triangle);//true,表明該對(duì)象是三角形  
  35. console.log(tri instanceof Polygon);//true,表明三角形也是多邊形 

#p#

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

  1. //  父類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. // 類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 子類  
  3.  * @param {Function} superCls 父類  
  4.  * @param {Object} param 父類構(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)用父類構(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中,子類Person在自身構(gòu)造方法中調(diào)用父類構(gòu)造方法super(legs),創(chuàng)建對(duì)象的時(shí)候直接將父類構(gòu)造參數(shù)legs:2傳進(jìn)去,不僅僅只傳自己的name:jack。上面JavaScript繼承是在extend時(shí)傳父類構(gòu)造參數(shù)(extend函數(shù)的第三個(gè)參數(shù)),而不是在new Man時(shí)將父類構(gòu)造參數(shù)傳過去。好,模擬Java來實(shí)現(xiàn)下extend,這里巧妙的在子類上暫存了父類引用。

繼承工具函數(shù)二

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

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

  1. function Woman(nationality,name) {  
  2.     Woman.supr.call(this,nationality);//和java有點(diǎn)類似哦,在子類中調(diào)用父類構(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也類似,即new的時(shí)候同時(shí)將父類構(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();    

父類,按原型方式寫,即屬性和方法都掛在原型上。

  1. /**  
  2.  *  父類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;} 

子類繼承與父類

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

繼承父類的屬性和方法后,再添加子類自有屬性,方法

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

測試如下,

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

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

#p#

繼承工具函數(shù)四

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

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

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

  1. /**  
  2.  *  父類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.  *  子類Man  
  12.  */ 
  13. function Man(nationality,name) {  
  14.     Man.supr.call(this,nationality); //很重要的一句,調(diào)用父類構(gòu)造器  
  15.     this.name = name;  
  16. }  
  17. Man.prototype.getName = function() {return this.name;}  
  18. Man.prototype.setName = function(n) {this.name=n;} 

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

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]);  

定義父類Person

  1. /**  
  2.  * 父類 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. }); 

子類Man

  1. /**  
  2.  * 子類 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 

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

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

【編輯推薦】

  1. 如何編寫高質(zhì)量的Javascript代碼
  2. 淺析JavaScript的寫類方式
  3. JavaScript跨域總結(jié)與解決辦法
  4. JavaScript版幾種常見排序算法分享
  5. 10個(gè)令人驚奇的HTML5和JavaScript效果
責(zé)任編輯:陳貽新 來源: 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繼承前端

2012-02-14 09:45:02

JavaScript

2011-08-31 14:48:33

JavaScript

2010-01-21 13:48:30

C++基類

2011-08-24 13:56:27

JavaScript

2010-09-28 14:12:50

Javascript

2021-12-04 11:17:32

Javascript繼承編程

2017-07-21 09:40:35

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

2009-08-13 18:15:06

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

2009-06-17 14:55:26

Hibernate數(shù)據(jù)

2009-07-14 11:34:42

MyEclipse斷點(diǎn)JavaScript

2021-07-27 22:56:00

JavaScript編程開發(fā)

2013-09-18 14:01:46

JavaScript

2011-05-25 16:23:35

Javascript類繼承

2009-07-08 17:42:26

this屬性

2009-09-07 05:24:22

C#窗體繼承
點(diǎn)贊
收藏

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