目录
继承
先看一个栗子:
function SuperType(){
this.property = true //注意这个property不属于原型上的属性,会在它的实例对象身上
}
Demo1.prototype.getSuperValue = function(){
return this.property
}
function SubType(){
this.subproperty = false
}
SubType.prototype = new SuperType(); //SubType的原型是SuperType的实例对象
SubType.prototype.getSubValue = function() //给SubType的原型上添加方法
{
return this.subproperty
}
let instance = new SubType();
console.log(instance.getSuperValue)
这个栗子特殊之处在于:SubType的原型是SuperType的实例对象。
得出以下结论,
SubType.Prototype._proto_ == SuperType.Prototype
instance._proto_ == SubType.Prototype
也就是说 SubType 的实例(instance)不仅能从SuperType的实例(SubType) 中继承属性和方法,而且还与SuperType的原型挂上了钩
注意点1:getSuperValue才是定义在原型上的方法,会被它的实例对象(SubType.Prototype)所共享,但是property不是定义在原型上的属性,它只会储存在它的实例对象身上。
注意点2:SubType.prototype 的constructor属性被重写为指向SuperType,所以Instance.constructor也指向SuperType.
原型链扩展了原型搜索机制,先在实例本身查找属性和方法,没有就去原型上搜索,也没有就去原型的原型上搜索。
instance.getSuperValue() 经过了三次搜索:
instance -> SubType.prototype -> SuperType.prototype
默认原型
默认情况下,所有引用类型都继承自Object,这也是通过原型链实现的。
任何函数的默认原型都是一个Object的实例,这就意味着实例内部有个指针[[Prototype]]也就是_proto_属性会指向Object.prototype。所以自定义类型能够继承toString() 、ValueOf()等所有默认方法。
回到这个栗子上,insatnce.toString()方法能被调用,实际上它是调用的Object.prototype身上的方法。
instance是 SubType 的实例,SubType 继承 SuperType,SuperType 继承 Object
原型与继承的关系
有两种方法确定原型和实例是否有关系,有两种方法
instanceof()
isPrototypeof()
console.log(instance instanceof Object); //true
console.log(instance instanceof SubType), //true
conole.log(Object.prototype.isPrototype(instance)) ; //true
关于原型上的方法
子类有时候需要覆盖父类的方法,或者增加父类没有的方法
function Father(){
this.name = "jack"
}
Father.prototype.sayName1= function(){
return this.name
}
function children(){
this.name = "jerry"
}
children.prototype = new Father();
//在子类的原型上添加父类没有的方法
children.prototype.sayName2 = funtion(){
return this.name
};
//覆盖已有方法
children.prototype.sayname1 = function()
{
return this.name
}
let instance = new children();
console.log(insatnce.sayName1()) //"jerry"
在这段代码中,instance调用的sayName1方法,正常来讲它应该会根据原型链查找规则找到Father原型上的方法,但是这个方法被children原型上的同名方法所屏蔽了。
值得注意的是:如果以字面量方式创建原型方法会破坏之前的原型链,因为这相当于重写了原型链。
function SuperType(){
this.property = true;
}
SuperType.prototype.getSuperValue = function(){
return this.property
};
function SubType(){
this.subproperty = false;
}
//实现继承
SubType.prototype = new SuperType();
//通过字面量方式创建对象,上一行无效
SubType.prototype= {
getSubValue()
{
return this.subproperty;
},
otherMethods(){
return false
}
}
let instance = new SubType();
console.log(instance.getSuperValue) //报错,找不到这个方法
子类的原型被对象字面量所覆盖了。覆盖后的原型是Object的实例,不再是SuperType的实例了。就不可能继承SuperType上的属性和方法了。
原型链的问题
问题1就是之前的属性是引用类型时,会被所有实例所共享;
问题2 子类型在实例化时不能给父类传递参数。