JavaScript繼承與聚合
一,繼承
第一種方式:類與被繼承類直接耦合度高
1,首先,準備一個可以被繼承的類(父類),例如
//創建一個人員類 function Person(name) {//現在Person裏面的域是由Person裏面的 來this來控制的 this.name=name; }
2,然後,有個需要繼承父類的子類
function Teacher(name,books) { Person.call(this,name);//相當於java中的super函數 在new Teacher時將Person的name初始化 this.books=books; }
說明一下:
(1)call方法可以將一個函數的對象上下文從初始化變成由this來決定 一個類去控制另一個類
(2)Teacher類去控制 Person類 用Teacher域裏面的 this來控制Person域裏面的 this
(3)調用 Perosn的構造函數,因為Perosn沒有用 new 所以是個空對象(模板) 顯示調用call方法,可以初始化 Person
3,最後,實現繼承
(步驟1)先繼承
Teacher.prototype=new Person(); Teacher.prototype.constructor=Teacher;//確保繼承後任然是Teacher自己的構造函數
(步驟2)為子類擴展一些方法,用於訪問從父類繼承的內容
Teacher.prototype.getBook=function () { return this.name+" "+this.books; }
(步驟3)使用已經繼承好的類
var jim=new Teacher("Jim","Javascript"); alert(jim.getBook())
總結:此種方法是直接在子類中顯示調用父類,耦合度高,復用性差。
第二種方式,使用封裝,完成程序中所用繼承操作
1,首先,準備一個可以被繼承的類(父類),例如
//創建一個人員類 function Person(name) {//現在Person裏面的域由Person裏面的來this來控制的 this.name=name; }
2,創建extend函數為了程序中所有的繼承操作(最重要的地方)
/*創建extend函數為了程序中所有的繼承操作*/ //subClass:子類 superClass:超類(2) function extend(subClass,superClass) { //1,使子類原型屬性等於父類的原型屬性 //初始化一個中間空對象,目的是為了轉換主父關系 var F = function () {}; F.prototype = superClass.prototype;
//2, 讓子類繼承F subClass.prototype = new F(); subClass.prototype.constructor = subClass;
//3,為子類增加屬性 superClass ==》原型鏈的引用 subClass.superClass = superClass.prototype;
//4,增加一個保險,就算你的原型類是超類(Object)那麽也要把你的構造函數級別降下來 if (superClass.prototype.constructor == Object.prototype.constructor) { superClass.prototype.constructor = superClass; } }
3,有一個需要繼承其他類的子類
function Author(name,books) { Author.superClass.constructor.call(this,name);//沒有直接寫父類,降低了耦合度 //Person.call(this,name) 直接寫Person代表其構造函數 this.books=books; this.getBooks=function () { return this.name+" "+this.books ; } }
4,最後,實現繼承
//繼承 extend(Author,Person);//(子類,父類)
5,使用已經繼承好的類
var peter=new Author("Peter","Javascript"); alert(peter.getBooks());
方式二圖解為:
這裏可能會有一個疑問就是為啥要使用中間類???
這裏假如沒有中間類的話,我們在實例化子類時就需要為父類傳遞一些相應的參數,這樣的話,該句代碼
Author.superClass.constructor.call(this,name);
就不能放在子類(Author)中,而是需要放入到extend中,這樣的話代碼的通用性就很低,故此需要使用中間類。
二,聚合
使用聚合的原因,有的時候不需要嚴格的繼承,我們真正需要的是一個類(或幾個類)中的一些函數。故此我們可以使用聚合 也就是使用 摻元類
對於聚合有兩種情況
第一種是聚合到 var a={}空類或者不是用function聲明的類中
1,首先,需要一個合適的可以被聚合的類(給體),此時需要在本類的內部進行擴展屬性,方法
var JSON={//寫到類的內部 toJsonString:function () { var output=[]; for(key in this){//this代表那個調用,就指向那個一個對象 output.push(key+"---->"+this[key]); } return output; } };
2,制作一個聚合函數(最重要)
/*聚合函數 receivingClass:接受聚合內容的類 givingClass:被聚合的目標類 * */ function mixin(receivingClass,givingClass){ for(methodName in givingClass){ if(!receivingClass.__proto__[methodName]){//判斷當前原型中是否含有即將要被聚合的方法,若沒有則聚合進來 receivingClass.__proto__[methodName]=givingClass[methodName];//直接獲得類中的方法,因為方法是直接寫在方法內部的。 } } }
3,接受聚合的類(受體)
var get={name:"Text",age:20};
4,實現將JSON類的方法聚合到類get中
mixin(get,JSON);//(受體,給體)
5,使用get類中聚合的方法
document.write(get.toJsonString().join(","));
第二種是聚合用function聲明的類中 var a=function(){}
1,首先,需要一個合適的可以被聚合的類(給體),此時需要在本類的原型對象上進行擴展屬性,方法
var JSON={}; JSON.prototype={//寫到類的原型對象上 toJsonString:function () { var output=[]; for(key in this){//this代表那個調用,就指向那個一個對象 output.push(key+"---->"+this[key]); } return output; } }
2,制作一個聚合函數
(2)制作聚合函數(receivingClass中聚合givingClass中的屬性,或者方法) function mixin(receivingClass,givingClass) { for(methodName in givingClass.prototype){ if(!receivingClass.prototype[methodName]){//判斷當前原型中是否含有即將要被聚合的方法,若沒有則聚合進來 receivingClass.prototype[methodName]=givingClass.prototype[methodName]; } } }
3,接受 聚合的類(受體)
var o=function () { this.name="聚合"; this.age=19; }
4,實現JSON類到o類的聚合(將JSON類中的方法聚合到o類中)
mixin(o,JSON);//(受體,給體)
5,使用o類中聚合而來的方法
var useO=new o(); document.write(useO.toJsonString().join(","));
第二種圖解理解為:
該方式屬於類o上一層的聚合。
JavaScript繼承與聚合