function SuperType(){
this.colors = ["red","blue","green"]; //设置属性
}
function SubType(){
// 继承SuperType
SuperType.call(this); //盗用构造函数的调用
}
let instance1 = new SubType();
instance1.colors.push("black");
console.log(instance1.colors); //["red","blue","green","black"]
let instance2 = new SubType();
console.log(instance2.colors); //["red","blue","green"]
一、继承
继承主要分为:接口继承和实现继承,接口继承只继承方法签名,后者则是继承实际的方法。
实现继承是ECMAScript唯一支持的继承方式,主要通过原型链实现。
二、实现原型链
实现继承的关键点,SubType没有使用默认原型,而是将其替换成一个新的对象,也就是SuperType 的实例。
这样就使SubType的实例能继承SuperType实例中的继承属性和方法。
根据原型搜索机制:读取实例上的属性时,先会读取实例,没找到,则读取实例的原型,实例原型的原型,直到搜索到该属性。
在本例子中,调用instance.getSuperValue(),搜索顺序 instance --> SubType.prototype --> SuperType.prototype。
原型链也有一定的问题:
三、盗用构造函数
可以解决原型包含引用值导致的继承问题。
基本思路:在子类构造函数中调用父类构造函数。可以使用call(),apply()以创建新的对象为上下文执性构造函数。
使用call(),apply()方法,SuperType构造函数在SubType的实例创建的新对象的上下文执性,也就是新的SubType对象运行了SuperType构造函数的所有初始化代码,使得每个实例都有自己的属性。
此方法有一个优点:可以在子类构造函数中向父类构造函数传参。如下述代码:
盗用构造函数的问题
四、组合继承
结合原型链和盗用构造函数的优点。
基本思路:使用原型链继承原型上的属性和方法,通过盗用构造函数继承实例属性。
结果就是,创建的两个实例既有自己的属性,同时又能共享相同的方法