类有三部分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
缺点:在使用构造函数继承时执行了一遍父类的构造函数,而在实现子类原型的类式继承时又调用一遍父类构造器,所以父类构造器调用了两遍。函数