继承算是JavaScript中的一大难点也是必须掌握的知识点。接下来我会列举一些咱们常见的继承并给出对应一些的code方便你们理解。javascript
1.类式继承,既子类原型继承父类实例化。可是当我利用new关键字实例化子类的时候,当我改变子类继承到父类属性的时候,会污染到再次实例化的子类它所继承到的属性。具体以下css
function SuperClass(){ this.superValue = true; this.languages= ['JS','JAVA']; } SuperClass.prototype.getSuperValue = function(){ return this.superValue; } function SubClass(){ this.subValue = false; } SubClass.prototype = new SuperClass(); SubClass.prototype.getSubValue = function(){ return this.subValue; } var sub = new SubClass(); console.log(sub.getSuperValue()); console.log(sub.getSubValue()); console.log(sub instanceof SuperClass); //true console.log(sub instanceof SubClass); //true console.log(SubClass instanceof SuperClass); //false console.log(SubClass.prototype instanceof SuperClass); //true console.log(sub.languages) //['JS','JAVA'] sub.languages.push('HTML'); var sub1 = new SubClass(); console.log(sub1.languages); //['JS','JAVA','HTML']
2.构造函数继承,即在子类构造函数中利用call()更改做用域,将子类变量在父类中执行一遍,从而完成继承。该继承方式只能继承父类构造函数中的属性和方法,并不能直接继承到父类原型。html
function SuperClass(id,books){ this.id = id; this.books = ['JS','JAVA']; } SuperClass.prototype.showBooks = function(){ return this.books; } function SubClass(id,books){ SuperClass.call(this,id,books) } var sub = new SubClass(); sub.books.push('CSS'); console.log(sub.books); //['JS','JAVA','CSS'] var sub1 = new SubClass('superClass'); console.log(sub1.books); //['JS','JAVA'] console.log(sub.showBooks()); //Uncaught TypeError: sub.showBooks is not a function
3.组合继承,即将类式继承和构造函数继承进行功能的结合,造成一个更为优良的继承方式。该继承结合了类式继承和构造函数继承,即继承了父类原型,又继承了父类构造函数中的属性和方法。这样的好处就是在用new关键字实例化一个子类的时候改变该子类继承到的属性,不会影响下一个实例化的子类继承到的属性。可是该继承方式的缺点就是子类原型继承父类实例化的时候,也会跑一次父类的构造函数。java
function SuperClass(name){ this.name = name; this.books = ['JS','JAVA']; } SuperClass.prototype.getName = function(){ return this.name; } function SubClass(name,time){ SuperClass.call(this,name); this.time = time; } SubClass.prototype = new SuperClass('superClass'); SubClass.prototype.getTime = function(){ return this.time; } var sub = new SubClass('superClass'); sub.books.push('CSS'); console.log(sub.books); //['JS','JAVA','CSS'] console.log(sub.getName()); //superClass var sub1 = new SubClass('superClass'); console.log(sub1.books); //['JS','JAVA']
4.原型式继承,它是对类式继承的一个封装,在原型式继承中会声明一个过渡对象,为的就是建立要返回的新的实例化对象。这里因为F过渡类的构造函数没有内容,因此开销比较小,使用起来也比较方便。但仍是有着类式继承同样的问题。ajax
function inheritObject(o){ //声明一个过渡函数 function F(){} //过渡对象的原型继承父对象 F.prototype = o; return new F(); } var book = { name:'js book', alikeBook:['css book','html book'] } var newBook = inheritObject(book); newBook.name = 'ajax book'; newBook.alikeBook.push('xml book'); var otherBook = inheritObject(book); otherBook.name = 'flash book'; otherBook.alikeBook.push('as book'); console.log(newBook.name); //ajax book console.log(newBook.alikeBook); //['css book','html book','xml book','as book'] console.log(otherBook.name); //flash book console.log(otherBook.alikeBook); //['css book','html book','xml book','as book'] console.log(book.name); //js book console.log(book.alikeBook); //['css book','html book','xml book','as book']
5.寄生式继承,它是对原型继承的第二次封装,让新建立的对象不单单有父类中的属性和方法并且还能够添加新的属性和方法。函数
//声明基对象 function inheritObject(o){ //声明一个过渡函数 function F(){} //过渡对象的原型继承父对象 F.prototype = o; return new F(); } var book = { name:'js book', alikeBook:['css book','html book'] } function createBook(obj){ //经过原型继承方式建立对象 var o = new inheritObject(obj); //拓展新对象 o.getName = function(){ console.log(this.name); }; //返回拓展后的新对象 return o; }
6.寄生组合式继承,它将寄生式继承和构造函数继承进行结合,造成一个完美的继承方式。this
/** * 寄生式继承 继承原型 * 传递参数 subClass 子类 * 传递参数 superClass 父类 */ function inheritObject(o){ //声明一个过渡函数 function F(){} //过渡对象的原型继承父对象 F.prototype = o; return new F(); } function inheritPrototype(subClass,superClass){ //复制一份父类的原型副本保存在变量 var p = inheritObject(superClass.prototype); //修正由于重写子类原型致使子类的constructor指向父类 p.constructor = subClass; //设置子类的原型 subClass.prototype = p; } //定义父类 function SuperClass(name){ this.name = name; this.colors = ['red','blue']; } //定义父类原型方法 SuperClass.prototype.getName = function(){ return this.name; } //定义子类 function SubClass(name,time){ //构造函数继承 SuperClass.call(this,name); //子类新增属性 this.time = time; } //寄生式继承父类原型 inheritPrototype(SubClass,SuperClass); //子类新增原型方法 SubClass.prototype.getTime =function(){ return this.time; } var test1 = new SubClass('js book',2014); var test2 = new SubClass('csc book',2013); test1.colors.push('black'); console.log(test1.colors); //['red','blue','black'] console.log(test2.colors); //['red','blue'] console.log(test2.getName()); console.log(test2.getTime());
至此,最终完美的寄生组合式继承便由此诞生了。prototype
此篇文章只是我我的的一些看法,但愿能够帮助到一些对于继承还比较模糊的小伙伴们。固然,若是有小伙伴觉着哪里有问题,欢迎指出,你们一块儿探讨交流。code