個人認為,javascript指令碼語言算是一種很複雜型的語言,它不像PHP那樣簡單,那是因為它本身的運用環境實在是多種多樣,不同的瀏覽器環境和其語言本身的獨特性質,決定了要學好javascript語言本身實在的太不容易了。相容不同環境和開發大型JS應用,談何容易。在這裡簡單的介紹一下一個工具方法,它可以簡化編寫javascript類繼承步驟。
首先要先回顧一下一般類繼承的寫法。
例子:
父類是 Rectangle . 子類是 PositionRectangle
//定義類 Rectanglefunction Rectangle(w,h){ this.width = w; this.height = h;} //定義類公有方法 area()Rectangle.prototype.area = function(){ return this.width * this.height; } //定義子類function PositionRectangle(x,y,w,h){ //調用父類的構造器 Rectangle.call(this,w,h); this.x = x; this.y = y;} //複製父類的原型鏈PositionRectangle.prototype = new Rectangle(); //刪除冗餘的屬性delete PositionRectangle.prototype.width;delete PositionRectangle.prototype.height; //重新設定原型鏈的constructor,指回PositionRectangle子類PositionRectangle.prototype.constructor = PositionRectangle; //子類的方法PositionRectangle.prototype.caculateArea = function(){ return this.x * this.y * this.width * this.height;}
測試:
var a = new PositionRectangle(1,2,3,4);var area = a.caculateArea();alert(area);
由上步驟可以,在JS裡面編寫類繼承需要不少步驟,接下來介紹的這個工具可以簡化這個步驟,這個方法是出自javascript權威指南,不過我不是很確定,原書的例子在borrows那裡出現了一些問題,所以加以修改和簡化,得出了一下一個版本。這個方法稍微有點複雜,其具體解決問題的步驟是:
擷取相關屬性——》構造原型鏈【調用父類構造方法構造原型鏈——》刪除父類的局部屬性和方法——》複製借用方法到原型鏈——》複製自訂方法到原型鏈——》設定constructor,superclass,classname】——》複製類本身屬性和方法——》返回類。
function defineClass(data){ // 擷取相關屬性 // data.name : 類的名稱 // data.extend : 父類的引用 // data.constructor : 建構函式 // data.methods : 類對象方法 // data.statics : 類本身的屬性和方法,不屬於對象 // data.borrows : 表示想從某個類裡面借用方法,borrows就是那個類 var classname = data.name; var superclass = data.extend || Object; var constructor = data.constructor || function(){}; var methods = data.methods || {}; var statics = data.statics || {}; var borrows; // 擷取borrows if(!data.borrows) borrows = []; else if(data.borrows instanceof Array) borrows = data.borrows; else borrows = [data.borrows]; // <!-- 構造類的原型鏈開始 --> // 建立一個父類的對象,用來構造原型鏈 constructor.prototype = new superclass(); // 擷取原型屬性和方法,去除局部定義的方法 for(var p in constructor.prototype){ if(constructor.prototype.hasOwnProperty(p)) delete constructor.prototype[p]; } // 將借用的類的方法全部複製到原型鏈中 for(var i = 0; i < borrows.length; i++){ var c = borrows[i]; for(var p in c.prototype){ if(typeof c.prototype[p] != "function") continue; constructor.prototype[p] = c.prototype[p]; } } // 將方法複製到原型鏈中,放在末尾可以覆蓋點在借用時的同名方法 for(var p in methods) constructor.prototype[p] = methods[p]; // 設定constructor 和 superclass 屬性 constructor.prototype.constructor = constructor; constructor.prototype.superclass = superclass; // 設定類名稱 if(classname) constructor.prototype.classname = classname; // <!-- 構造類的原型鏈結束 --> // 複製屬於類本身的屬性 for(var p in statics) constructor[p] = statics[p]; // 返回被構造好的類 return constructor;}
這個方法需要一個data對象為參數,具體屬性如下:
// data.name : 類的名稱
// data.extend : 父類的引用
// data.constructor : 建構函式
// data.methods : 類對象方法
// data.statics : 類本身的屬性和方法,不屬於對象
// data.borrows : 表示想從某個類裡面借用方法,borrows就是那個類
// data.provides : 查詢是否本類提供了provides裡面所有類的所有方法,如果沒有,則中斷構造過程,拋出異常
一個簡單的例子,實現了和上面哪個例子的同一個繼承:
var Person = defineClass({ name : "Person", methods : { say : function(){ alert("hello!") } }}) var Rectangle = defineClass({ name : "Rectangle", constructor : function(w,h){ this.width = w; this.height = h; }, methods : { area : function(){ return this.width * this.height; } }}); var PositionRectangle = defineClass({ name : "PositionRectangle", extend : Rectangle, constructor : function(x,y,w,h){ this.superclass(w,h); this.x = x; this.y = y; }, methods : { caculateArea : function(){ return this.x * this.y * this.width * this.height; } }, statics : { positionNow : "positionNow" }, borrows : Person}) var a = new PositionRectangle(1,2,3,4);var area = a.caculateArea();alert(area)alert(PositionRectangle.positionNow);// 類方法a.say();// 借用方法
對於大型的JS應用,如果用JS構造大型的富用戶端應用,或者實現JS效果架構,類繼承的使用絕對是核心技術。要學好JS,切勿好高騖遠。
原文連結:http://zhenpengday.blog.163.com/blog/static/165988143201011501630727/