说起这种继承,懂面向对象的朋友都知道,大多数oo语言有两种,一种是接口继承(只继承方法签名);一种是实现继承(继承实际的方法)
但是js中没有签名,所以只实现了继承,通过原型链实现。让我们正式讨论js中的继承
回顾:构造函数、原型和实例之间的关系
每个构造函数都有一个原型对象(人。原型);原型对象都包含指向构造函数的指针);每个实例都包含一个指向原型对象的指针(不可见的原型指针)
原型链是怎么来的?
构造函数的原型对象是另一个构造函数的实例;此构造函数的原型对象将有一个(不可见的_proto_指针)指向另一个构造函数的原型对象;
然后当另一个原型对象是另一个构造器实例时会发生什么,于是它一层一层地前进,形成一个原型链;让我们具体看一下
//第一个构造函数;有一个属性和一个原型方法functionsupertype () {this。属性=true} super type . prototype . getsuper value=function(){ return this . property }//第二个构造函数;目前有一个属性functionsubtype () {this。subproperty=false }//它继承了SuperTypeSubType原型成为SuperType的实例;其实就是重写SubType的原型对象;遗传亚型。prototype=new SuperType()//到SuperType原型对象。现在这个构造函数有两个属性(一个是自己的子属性,一个是带有原型对象的继承属性)。两种方法(原型对象的getSubValue,原型对象的原型对象的Getsupervalue)subtype . prototype . getSubValue=function(){ return this . subproperty } var instance=new subtype()//创建第二个构造函数实例控制台。日志(实例。getSupervalue())//true;首先找出实例中是否存在此方法;显然不是,找出SubType原型对象是否有这个方法;否,查找SubType原型对象的原型对象;显然有一个注意事项:实例的构造函数现在指向SuperType构造函数;因为原始的SubType.prototype已经被重写,所以它的内部构造函数指向构造函数SuperType以及SubType.prototype的原型对象的构造函数;至于原型搜索机制是如何工作的,请仔细看看上面的代码,相信可以
1.1完整的原型
我已经在原型部分提到了一些东西。再说一遍。一个完整的原型包括对象。
所有函数的默认原型都是对象的实例;每个默认原型都有一个指向对象原型的指针;因此,自定义类型继承诸如toString和valueOf之类的方法
而Object.prototype的_proto_指针指向空值以结束原型链。以Person构造函数为例,查看完整的原型链图
1.2原型与实例的关系
第一个使用instanceof运算符:出现在测试用例和原型链中的构造函数,结果为真
第二种方法是isPrototypeOf():只要原型已经出现在原型链中,就可以说是从原型链中派生出来的实例的原型
Console.log(对象的实例实例)//为true console.log(超类型的实例实例)console.log(子类型的实例实例)console.log(对象。prototype . is prototype of(instance))//都是真正的console.log (supertype。prototype.isprototypeof(实例))console.log(子类型。prototype . is prototype of(instance))1.3仔细定义方法
注意:向原型对象添加方法必须放在替换原型后面,因为在替换原型之前找不到方法,原型会被重写;
注意:通过原型链继承时,不能使用对象文字创建原型方法,因为原型链也会被重写。
函数SuperType(){ this。属性=true} SuperType。原型。GetSuperVaLue=function(){返回这个。property } function SuBject(){ this。sub属性=false }//继承SuperType SupLe。prototype=new SuperType()//使用字面量添加新方法,导致上一行无效因为现在的原型替换了目标实例而非超类型的实例,关系中断亚型。prototype={ getsubvalue e : function(){ return this。子属性;},somother method : function(){ return false } };var实例=new SupLe()。控制台。日志(实例。getsuper value())//错误1.4原型链的问题
1、包含引用类型值的原型:当实例是另一函数的原型时,引用类型值就会变成原型上的属性,就会被另一函数的实例所共享。
函数SuperType(){ this。colors=['黄色','红色','橄榄]}函数SuperType(){ } SuperType。prototype=new SuperType()//color实际上就是原型上的了var实例1=新的SubType()实例1。颜色。推动('紫色)var实例2=new SubType()控制台。日志(实例1。colors==实例2。颜色)//真2、创建子类型实例时,不能向超类型的构造函数传递参数(没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数)
在子类型构造函数的内部调用超类型构造函数(函数是特定环境中执行代码的对象,可以通过应用或呼叫调用)
函数SuperType(){ this。color=['黄色','红色','橄榄]}函数SuperType(){//继承了超类型超类型。调用(this)} var实例1=new SubType()实例1。颜色。推动('紫色)var实例2=new SubType()控制台。日志(实例1。颜色)/['黄色','红色','橄榄色','紫色]控制台。日志(实例2。颜色)//['黄色','红色','橄榄色'] //传递参数函数SuperType(name){ this。name=name }函数SuperType(){ SuperType。称(这个为‘double’)这个。age=12 } var实例1=new SuperType()控制台。日志(实例1。名称)//双控制台。日志(实例1。年龄)//12问题:仅仅借鉴构造函数,那么避免不了构造函数的问题,方法都在构造函数定义了,函数无法复用
1、原型式继承
克罗克福德写的;借助原型可以基于已有的对象创建新对象,同时不必创建自定义类型
函数对象(o){ //本质上对象()函数对其中对象的浅复制函数F(){} //创建一个新的构造函数F.prototype=o //构造函数原型为传入的对象返回新的F() //返回构造函数的实例} var person={ name:'double ',friends 3360[' Tom ',' jack ',' Mike ']} var person 1=object(person)//事实上为原型共享人1。姓名='灰色'人1。朋友。按压(“单”)控制台。日志(人1。朋友)/['汤姆','杰克','迈克','单身']var person 2=object(人)person 2。name=' red '控制台。日志(人员2。朋友)//['汤姆','杰克','迈克','单身' ES5为了规范原型式的继承,有个Object.create()来方便,IE9以上可以;只是想一个对象和另一个对象保持类似的情况,完全可以这种方法
var person={ name:'double ',friends 3360[' Tom ',' jack ',' Mike ']} var person 1=object。创造(人)人1。姓名='单身'人1。朋友。push(' singles ')var person 2=object。创建(个人)控制台。日志(人1。朋友==人2。朋友)//真//对象。创建()接受两个参数,一个为作为新对象原型的对象,一个为新对象定义额外属性对象var person={ name:'double ',friends 3360[' Tom ',' jack ',' Mike ']} var person 1=object。create(person,{ name : { value : ' single '//每个属性都是通过自己描述符定义的} })2、寄生式继承
思路和原型式继承一脉相承,创建一个用于封装继承过程的函数,内部通过方式增强对象,返回对象;主要考虑对象时使用
函数对象(o){函数F(){} F.prototype=o返回新的F() }函数createPerson(原始){ var clone=object(原始)//继承原型克隆人。say name=function(){ alert(' name ')}返回克隆} var person={ name : ' double ',friends 3360[' single ',' tom ',' jack ']} var person 1=createPerson(person)person 1。说出姓名()//姓名引用类型值还是共享的3、寄生组合继承
组合继承是继承中常常用到的,但是会调用两次超类型构造函数;寄生组合继承就是为了解决这个问题的
函数对象(o){函数F()} { F .原型=o返回新的F()}函数继承原型(subType,SuperType){ var prototype=object(SuperType)//创建对象(超类型实例)原型。构造函数=subType//增强对象subType.prototype=prototype //指定对象(原型赋予实例)}函数SuperType(姓名、性别){ this。name=为此命名。性=性这个。colors=[' red ']} SuperType。原型。说出name=function(){ alert(this。name)} function SuperType(姓名、性别、年龄){ SuperType.call(this,姓名、性别)this。age=age }继承原型(SuperType,SuperType) //目前子类型。原型什么都没有亚型。原型。SayAge=function(){//为子类型。原型添加个方法警惕(这个。age)} var person 1=new SubType(' double ',' man ',34)控制台。日志(人1。名称)//SuperType这是个bug控制台。日志(人1。性)//男人控制台。日志(人1。颜色)/['红色']人1。sayage()//34到此,差不多结束啦,感谢你对我们的支持,希望我们整理的内容能够帮助到你。