1> 原型及原型链在继承中起到了关键的做用。因此你必定要理解他们。
2> 不会JS中的OOP,你也太菜了吧!(第一篇)html
原型链继承是经过建立Super的实例,并将该实例赋值给Sub.prototype来实现的。函数
实现的本质是:重写子类型的原型对象,代之以超类型的实例。this
function Super(){ this.name = 'JChen___'; } Super.prototype.getSuperName = function(){ return this.name; } function Sub(){ this.subname = 'JChen___son'; } Sub.prototype = new Super(); //原型继承体如今这里 Sub.prototype.getSubName = function(){ return this.subname; } var instance = new Sub();
注意:此时instance.constructor如今指向的是Super的,这是由于Sub.prototype指向了Super.prototype,而Super.prototype.constructor = Super。spa
原型链的问题:相似于利用原型建立对象,原型共享的特性也是原型链继承的最大问题。prototype
在解决原型中包含引用类型值所带来的问题的过程当中,咱们开始使用一种叫作借用构造函数的技术。code
这种技术的基本思想至关简单:在子类型构造函数的内部调用超类型构造函数。htm
这样一来,就会在新子类对象上执行超类函数中定义的全部对象初始化代码。结果,每一个子类的实力都会有本身的超类中属性的副本了。对象
function Super2(name){ this.colors = ['red', 'blue']; this.name = name; } function Sub2(){ Super2.call(this, 'JChen___2'); //借用构造函数技术体如今这里 this.age = 29; } var instance1 = new Sub2(); instance1.colors.push('black'); var instance2 = new Sub2(); instance2.colors.push('green');
借助构造函数继承的问题:blog
1): 方法都在构造函数中定义,没法复用。继承
2): 在超类型的原型中的方法对子类是不可见的。
组合继承指的是将原型链和借用构造函数的技术组合到一块,从而发挥两者之长的一种继承模式。
组合继承的思路:使用原型链实现对方法和属性的继承,经过借用构造函数实现对实例属性的继承。
function Super3(name){ this.name = name; this.colors = ['red', 'blue']; } Super3.prototype.sayName = function(){ return this.name; } function Sub3(name, age) { Super3.call(this, name); this.age = age; } Sub3.prototype = new Super3(); //解决借用构造函数技术的缺点 Sub3.prototype.constructor = Sub3; //纠正原型继承改变了的构造函数 Sub3.prototype.sayAge = function(){ return this.age; }
组合继承避免了原型链和借用构造函数的缺陷,融合了他们的优势,成为JavaScript中最经常使用的继承模式。
组合继承的问题:两次调用超类构造函数。
原型式继承的思路:借助原型能够基于已有的对象建立新对象,同时还没必要所以建立自定义类型。
function object(o){ //原型式继承的关键 function F(){} F.prototype = o; return new F(); } var person = { name: 'JChen___4', colors: ['blue'] } var person1 = object(person); person1.name = 'JChen___4___2' person1.colors.push('red'); var person2 = object(person); person2.name = 'JChen___4___3'; person2.colors.push('green');
原型式继承的问题:同原型链同样,他也有共享的劣势。
寄生式继承的思路:建立一个仅用于封装继承过程的函数,该函数内部以某种方式来加强对象,最后再返回该对象
function createAnother(origin){ //寄生式继承的关键 var clone = object(origin); clone.sayHi = function(){ return 'Hi'; }; return clone; } var person = { name: 'JChen___4', colors: ['blue'] } var person1 = createAnother(person);
寄生式继承的问题:像构造函数同样,因为不能作到函数的复用而下降效率。
寄生组合式继承:经过借用构造函数来借用属性,经过原型链的混成形式来继承方法。
其背后的思想是:没必要为了指定子类型的原型而调用超类型的构造函数,咱们须要的无非就是超类型的一个副本而已。
function object(o){ function F(){} F.prototype = o; return new F(); } function inheritProto(subType, superType){ //避免第一调用构造函数的关键 var proto = object(superType.prototype); proto.constructor = subType; subType.prototype = proto; } function Super6(name){ this.name = name; this.colors = ['red', 'blue']; } Super6.prototype.sayName = function(){ return this.name; } function Sub6(name, age){ Super6.call(this, name); this.age = age; } inheritProto(Sub6, Super6); Sub6.prototype.sayAge = function(){ return this.age; } var instance1 = new Sub6('JChen___6', '12'); instance1.colors.push('black');
开发人员广泛认为寄生组合式继承是引用类型最理想的继承范式。
这就是JavaScript中的6种继承方式,若是你们可以画出每一个继承的原型链关系图,那么继承就是小菜一碟了。