類有三部分javascript
類的原型對象的做用就是爲類的原型添加共有方法,但類不能訪問這些屬性和方法,只有經過原型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
缺點:在使用構造函數繼承時執行了一遍父類的構造函數,而在實現子類原型的類式繼承時又調用一遍父類構造器,所以父類構造器調用了兩遍。函數