原型链继承
SubType.prototype = new SuperType();
注意点
//使用字面量添加新方法,会导致上一行代码无效
SubType.prototype = {
getSubValue : function (){
return this.subproperty;
},
someOtherMethod : function (){
return false;
}
};
单纯使用原型链继承会存在引用数据共用的问题。
借用构造函数继承
基础
function SubType(){
//继承了 SuperType
SuperType.call(this);
}
可以实现传参
function SubType(name,age){
//继承了 SuperType,同时还传递了参数
SuperType.call(this, age);
//实例属性
this.age = age;
}
存在的问题是方法都在构造函数里面定义,而无法继承到SubType里面的方法,淡化了函数复用概念
组合继承
组合原型链和借用构造继承
function SubType(name, age){
//继承属性
SuperType.call(this, name);
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
//弥补因重写原型而失去的默认的 constructor 属性
SubType.prototype.constructor = SubType;
//实现在原型链增加共用函数 达到函数复用
SubType.prototype.sayAge = function(){
alert(this.age);
};
这属于很常用的继承模式
原型式继承
function myobject(o){
function F(){}
F.prototype = o;
return new F();
}
或者使用ES6中的Object.create()
可以实现一样的效果
实际上就是创建了一个临时性的构造函数,然后将传入的对象作为这个构造函数的 原型,最后返回了这个临时类型的一个新实例。
当然这样实现的都是浅拷贝,副本对于原函数的引用类型一样是共享的。
寄生继承
寄生式(parasitic)继承是与原型式继承紧密相关的一种思路
function createAnother(original){
var clone = object(original); //通过调用函数创建一个新对象
clone.sayHi = function(){ //以某种方式来增强这个对象
alert("hi");
};
return clone; //返回这个对象
}
其实就是多个给构造函数加东西的过程,也没有实现函数的复用。
寄生组合继承
对于组合继承不够优秀的补充,组合继承调用了两次超类型构造函数,存在属性覆盖的情况。
基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型 原型的一个副本而已。
function inheritPrototype(subType, superType){
var prototype = object(superType.prototype); //创建对象
prototype.constructor = subType; //增强对象
subType.prototype = prototype; //指定对象
}
高效率体现在它只调用了一次 SuperType 构造函数,并且因此避免了在 SubType. prototype 上面创建不必要的、多余的属性。
实例
//寄生组合继承
//超构造函数
function person(name='我是默认姓名'){
this.name=name
this.color=['1','2','3']
}
person.prototype.getcolor=function(){
return this.color
}
//构造函数
function people (age,name){
//继承属性
person.call(this,name)
this.age=age
}
//实现部分
people.prototype=Object.create(person.prototype)
//弥补因重写原型而失去的默认的 constructor 属性
people.prototype.constructor=people
person.prototype.addcolor=function(arr){
this.color.push(...arr)
}
//实例
var fan1=new people('19','fanfan')
var fan2=new people('20','xixi')
fan1.addcolor(['add1','add2'])
console.log(fan1.getcolor()); //"1", "2", "3", "add1", "add2"
console.log(fan2.getcolor()); //"1", "2", "3"
ES6的继承
class注意点
- class相当于es5中的构造函数
- class定义方法时候,不能加function,方法也是定义在class的原型链上。
- class定义的方法都是不可枚举的。
- class只能定义方法,不用定义对象,变量
- class默认严格模式,全局this指向undefined
- es5中的constructor为隐式属性
class person{
constructor(name='fanfan',age){
this.name=name
this.age=age
this.color=[1.2,3]
}
getmyname(){
//调用this依旧指向子类
console.log(this.name);
return this.color
}
}
//继承
class people extends person{
constructor(name='xixi',age){
super(name,age)
this.name=name
}
getname(){
return super.getmyname()
}
}
var fan1=new people('??','200')
console.log(fan1.getname()); //?? [1.2, 3]