javaScript面向對象編程-繼承(一)

類有三部分javascript

  1. 構造函數內的,供實例化對象複製用的
  2. 構造函數外的,直接經過點語法添加的,供類使用,實例化對象訪問不到
  3. 類的原型中的,實例化對象能夠經過其原型鏈間接地訪問到,也是供全部實例化對象所共用的。

類式繼承

類的原型對象的做用就是爲類的原型添加共有方法,但類不能訪問這些屬性和方法,只有經過原型prototype來訪問。css

//類式繼承
//聲明父類
function SuperClass() {
    this.superValue = true;
}
//爲父類添加共有方法
SuperClass.prototype.getSuperValue = function () {
    return this.superValue;
};
//聲明子類
function SubClass() {
    this.subValue = false;
}
//繼承父類
SubClass.prototype = new SuperClass();
//爲子類添加共有方法
SubClass.prototype.getSubValue = function () {
    return this.subValue;
};
var instance = new SubClass();
console.log(instance.getSuperValue());//true能夠這樣使用子類
console.log(instance.getSubValue());//false
console.log(instance instanceof SuperClass);//true
console.log(instance instanceof SubClass);//true
console.log(SubClass instanceof SuperClass);//false

類式繼承的兩個缺點:
1、子類經過其原型prototype對父類實例化,繼承了父類。父類的共有屬性要是引用類型,就會在子類中被全部實例共用,一個子類的實例更改子類原型從父類構造函數中繼承的共有屬性就會直接影響其餘子類。
2、因爲子類實現的繼承是靠其原型prototype對父類的實例化實現的,所以在建立父類的時候,沒法向父類傳遞參數,在實例化父類的時候也沒法對父類構造函數內的屬性進行初始化。html

構造函數繼承

//構造函數式繼承
//聲明父類
function SuperClass(id) {
    //引用類型共有屬性
    this.books = ['javascript','html','css'];
    //值類型共有屬性
    this.id = id;
}
//父類聲明原型方法
SuperClass.prototype.showBooks = function () {
    console.log(this.books);
}
//聲明子類
function SubClass(id) {
    //繼承父類
    SuperClass.call(this,id);//將子類的變量在父類中執行一遍
}
//建立第一個子類實例
var instance1 = new SubClass(10);
var instance2 = new SubClass(11);
instance1.books.push('設計模式');
console.log(instance1.books);//[ 'javascript', 'html', 'css', '設計模式' ]
console.log(instance1.id);//10
console.log(instance2.books);//[ 'javascript', 'html', 'css' ]
console.log(instance2.id);//11
instance1.showBooks();//[ 'javascript', 'html', 'css', '設計模式' ]

因爲這種類型的繼承沒有涉及原型prototype,全部父類的原型方法天然不會被子類繼承,而若是想要被子類繼承就必須放在構造函數中,這樣建立的每一個實例都會單獨擁有一份而不能共用,違背了代碼複用原則。java

組合繼承

前面兩種模式的特色:類式繼承經過子類的原型prototype對父類實例化實現的,構造函數式繼承是經過在子類的構造函數做用環境中執行一次父類的構造函數來實現的。組合繼承同時作到了這兩點。設計模式

//組合式繼承
//聲明父類
function SuperClass(name) {
    //值類型共有屬性
    this.name = name;
    //引用類型共有屬性
    this.books = ['html','css','javaScript'];
}
//父類原型共有方法
SuperClass.prototype.getName = function () {
    console.log(this.name);
}
//聲明子類
function SubClass(name,time) {
    //構造函數式繼承父類name屬性
    SuperClass.call(this,name);
    //子類中新增共有屬性
    this.time = time;
}
//類式繼承 子類原型繼承父類
SubClass.prototype = new SuperClass();
//子類原型方法
SubClass.prototype.getTime =function () {
    console.log(this.time);
}
var instance1 = new SubClass('js',2018);
instance1.books.push('設計模式');
console.log(instance1.books);//[ 'html', 'css', 'javaScript', '設計模式' ]
instance1.getName();//js
instance1.getTime();//2018
var instance2 = new SubClass('css',2018);
console.log(instance2.books);//[ 'html', 'css', 'javaScript' ]
instance2.getName();//css
instance2.getTime();//2018

缺點:在使用構造函數繼承時執行了一遍父類的構造函數,而在實現子類原型的類式繼承時又調用一遍父類構造器,所以父類構造器調用了兩遍。函數

相關文章
相關標籤/搜索