es6之前的作法:
方法一:原型链 (与java的类多层继承思想类似,python可以多重继承,MixIn是常用的设计思想)
缺点: 当父级的属性有引用类型的时候,任意一个实例修改了这个属性,其他实例都会受影响
function SuperType() {
this.property = true;
}
SuperType.prototype.getSuperValue = function() {
return this.property;
}
function subType() {
this.property = false;
}
//继承了SuperType
SubType.prototype = new SuperType();
SubType.prototype.getSubValue = function (){
return this.property;
}
var instance = new SubType();
console.log(instance.getSuperValue());//true
方法二:借用构造函数
缺点:创建多个实例 , 父类的方法会被创建多次。instance1.colors == intance2.colors // false
function SuperType(){
this.colors = ["red","blue","green"];
}
function SubType(){
SuperType.call(this);//继承了SuperType
}
var instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors);//"red","blue","green","black"
var instance2 = new SubType();
console.log(instance2.colors);//"red","blue","green"
方法三:组合继承
缺点: 父类的构造器被调用了两次
function SuperType(name) {
this.name = name;
this.colors = ["red","blue","green"];
}
SuperType.prototype.sayName = function() {
console.log(this.name);
}
function SubType(name, age) {
SuperType.call(this,name);//继承属性
this.age = age;
}
//继承方法
SubType.prototype = new SuperType();
Subtype.prototype.constructor = Subtype;
Subtype.prototype.sayAge = function() {
console.log(this.age);
}
var instance1 = new SubType("EvanChen",18);
instance1.colors.push("black");
consol.log(instance1.colors);//"red","blue","green","black"
instance1.sayName();//"EvanChen"
instance1.sayAge();//18
var instance2 = new SubType("EvanChen666",20);
console.log(instance2.colors);//"red","blue","green"
instance2.sayName();//"EvanChen666"
instance2.sayAge();//20
方法四:原型式继承
用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随意增添属性的实例或对象,结果是将子对象的__proto__
指向父对象
缺点:共享引用类型 (相互影响)
function object(o) {
function F(){}
F.prototype = o;
return new F();
}
//示例
var person = {
name:"EvanChen",
friends:["Shelby","Court","Van"];
};
var anotherPerson = Object.create(person);
anotherPerson.name = "Greg";
anotherPerson.friends.push("Rob");
var yetAnotherPerson = Object.create(person);
yetAnotherPerson.name = "Linda";
yetAnotherPerson.friends.push("Barbie");
console.log(person.friends);//"Shelby","Court","Van","Rob","Barbie"
方法五:寄生组合式继承
改进组合继承,利用寄生式继承的思想继承原型
function inheritPrototype(subType, superType){
var protoType = Object.create(superType.prototype); //创建对象
protoType.constructor = subType; //增强对象
subType.prototype = protoType; //指定对象
}
function SuperType(name){
this.name = name;
this.colors = ["red", "blue", "green"];
}
SuperType.prototype.sayName = function(){
alert(this.name);
}
function SubType(name, age){
SuperType.call(this, name);
this.age = age;
}
inheritPrototype(SubType, SuperType)
SubType.prototype.sayAge = function(){
alert(this.age);
}
var instance = new SubType("Bob", 18);
instance.sayName();
instance.sayAge();
==== Es6 class继承
- 继承中,如果实例化子类输出一个方法,先看子类有没有这个方法,如果有就先执行子类的
- 继承中,如果子类里面没有,就去查找父类有没有这个方法,如果有,就执行父类的这个方法(就近原则)
- 如果子类想要继承父类的方法,同时在自己内部扩展自己的方法,利用super 调用父类的构造函数,super 必须在子类this之前调用
// 父类有加法方法
class Father{
constructor(x,y) {
this.x = x ;
this.y = y ;
}
sum() {
console.log(this.x + this.y);
}
}
// 子类继承父类加法的方法, 同时 扩展减法方法
class Son extends Father {
constructor (x,y){
// 利用super调用父类的构造函数
// super必须在子类this之前调用
super(x,y);
this.x = x;
this.y = y;
}
subtract(){
console.log(this.x - this.y);
}
}
var son = new Son(20,10);
son.subtract();//10
son.sum(); //30