js面向对象之继承知识详解

说到这个继承,了解object-oriented的朋友都知道,大多oo语言都有两种,一种是接口继承(只继承方法签名);一种是实现继承(继承实际的方法)本文主要和大家介绍js面向对象之继承的相关知识,以及分享了读者弄明白这个知识点的学习心得,对此有需要的朋友参考下吧。希望能帮助到大家。

奈何js中没有签名,因而只有实现继承,而且靠的是原型链实现的。下面正式的说一说js中继承那点事儿

1、原型链

原型链:实现继承的主要方法,利用原型让一个引用类型继承另一个引用类型的属性和方法。

回顾:构造函数,原型,实例三者的关系

每一个构造函数都有一个原型对象(Person.prototype);原型对象都包含指向构造函数的指针(constructor);每个实例都包含指向原型对象的指针(看不见的_proto_指针)

原型链是怎么来的呢?

某个构造函数的原型对象是另一个构造函数的实例;这个构造函数的原型对象就会有个(看不见的_proto_指针)指向另一个构造函数的原型对象;

那么另一个原型对象又是其他的构造函数实例又会怎么样,就这样层层递进,形成原型链;来具体看一下吧

    //第一个构造函数;有一个属性和一个原型方法    function SuperType(){        this.property=true;    }         SuperType.prototype.getSuperValue=function(){        return this.property    }    //第二个构造函数;目前有一个属性    function SubType(){        this.subproperty=false    }        //继承了SuperType;SubType原型成了SuperType的实例;实际就是重写SubType的原型对象;给SuperType原型对象继承了    SubType.prototype=new SuperType()        //现在这个构造函数有两个属性(一个本身的subproperty,一个继承的存在原型对象的property);两个方法(一个原型对象的getSubValue,一个原型对象的原型对象的getSuperValue)    SubType.prototype.getSubValue=function(){        return this.subproperty    }        var instance=new SubType()  //创建第二个构造函数的实例    console.log(instance.getSuperValue())  //true 先查找instance这个实例有没有此方法;显然没有,再查找SubType原型对象有没有此方法;也没有,再查找SubType原型对象的原型对象;显然是存在的

登录后复制

注意:instance的constructor现在指向的是SuperType这个构造函数;因为原来的SubType.prototype被重写了,其内部的constructor也就随着SubType.prototype的原型对象的constructor指向构造函数SuperType;至于原型搜索机制是怎么样运行的,请仔细看上面的代码,相信你是可以的

1.1完整的原型

在原型那节已经提了些,还是再说一下。完整的原型包括Object。

所有函数的默认原型都是Object的实例;每个默认原型都有个_proto_指针指向Object.prototype;因此自定义类型都继承如toString,valueOf的方法

而Object.prototype的_proto_指针指向null来结束原型链。以Person构造函数为例,看看完整的原型链图

js面向对象之继承知识详解

1.2原型和实例的关系判断

第一种使用instanceof操作符: 测试实例和原型链中出现的构造函数,结果为true

第二种使用isPrototypeOf()方法: 只要是原型链中出现过的原型,都可以说是该原型链所派生的实例的原型

    console.log(instance instanceof Object)   //都为true    console.log(instance instanceof SuperType)    console.log(instance instanceof SubType)       console.log(Object.prototype.isPrototypeOf(instance)) //都为true    console.log(SuperType.prototype.isPrototypeOf(instance))    console.log(SubType.prototype.isPrototypeOf(instance))

登录后复制

1.3谨慎定义方法

注意:给原型对象添加方法,一定放在替换原型的后面,因为放在替换原型之前是找不到了,原型会被重写的;

注意:在通过原型链继承时,不能使用对象字面量创建原型方法,因为也会重写原型链;

    function SuperType(){        this.property=true;    }         SuperType.prototype.getSuperValue=function(){        return this.property    }        function SubType(){        this.subproperty=false    }        //继承SuperType    SubType.prototype=new SuperType()        //使用字面量添加新方法,导致上一行无效   因为现在的原型替换了Object实例而非SuperType的实例,关系中断    SubType.prototype={       getSubValue:function(){           return this.subproperty;       },       somOtherMethod:function(){           return false       }    };    var instance=new SubType()    console.log(instance.getSuperValue())  //error

登录后复制

1.4原型链的问题

1、包含引用类型值的原型:当实例是另一函数的原型时,引用类型值就会变成原型上的属性,就会被另一函数的实例所共享。

    function SuperType(){       this.colors=["yellow","red","olive"]    }    function SubType(){    }    SubType.prototype=new SuperType()  //color实际上就是原型上的了    var instance1=new SubType()    instance1.colors.push("purple")    var instance2=new SubType()    console.log(instance1.colors==instance2.colors)  //true

登录后复制

2、创建子类型实例时,不能向超类型的构造函数传递参数(没有办法在不影响所有对象实例的情况下,给超类型的构造函数传递参数)

2、借助构造函数

为了解决原型中包含引用类型值带来的问题,利用构造函数来解决

在子类型构造函数的内部调用超类型构造函数(函数是特定环境中执行代码的对象,可以通过apply或call调用)

    function SuperType(){        this.color=["yellow","red","olive"]    }    function SubType(){        //继承了SuperType        SuperType.call(this)    }    var instance1=new SubType()    instance1.color.push("purple")    var instance2=new SubType()    console.log(instance1.color)  //["yellow","red","olive","purple"]    console.log(instance2.color)  //["yellow","red","olive"]    //传递参数    function SuperType(name){       this.name=name    }    function SubType(){        SuperType.call(this,"double")        this.age=12    }    var instance1=new SubType()    console.log(instance1.name)  //double    console.log(instance1.age)  //12

登录后复制

问题:仅仅借鉴构造函数,那么避免不了构造函数的问题,方法都在构造函数定义了,函数无法复用

3、组合继承(常用的还是组合,和原型与构造结合一样)

    function SuperType(name){        this.name=name;        this.color=["yellow","red","olive"];    }    SuperType.prototype.sayName=function(){        console.log(this.name);    }     function SubType(name,age){        //继承属性,创建属性副本        SuperType.call(this,name);        this.age=age;    }        //继承属性和方法,只是原型中属性被后来的函数调用生成的属性副本遮盖    SubType.prototype=new SuperType();    alert(SubType.prototype.constructor)  //指向的是SuperType    SubType.prototype.constructor=SubType; //将constructor回归到SubType构造函数身上    SubType.prototype.sayAge=function(){        console.log(this.age)    }            var instance1=new SubType("double",23)    instance1.color.push("pink")    console.log(instance1.color)     //["yellow","red","olive","pink"]    instance1.sayName()         //double    instance1.sayAge()          //23    var instance2=new SubType("single",34)    console.log(instance2.color)     //["yellow","red","olive"]    instance2.sayName()         //single    instance2.sayAge()          //34

登录后复制

还有其他的继承,花点时间写一下

1、原型式继承

克罗克福德写的;借助原型可以基于已有的对象创建新对象,同时不必创建自定义类型

    function object(o){      //本质上object()函数对其中对象的浅复制        function F(){}      //创建一个新的构造函数        F.prototype=o      //构造函数原型为传入的对象      return new F()      //返回构造函数的实例    }    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=object(person)   //事实上为原型共享    person1.name="grey"    person1.friends.push("single")        console.log(person1.friends)  //["tom", "jack", "mike", "single"]    var person2=object(person)    person2.name="red"    console.log(person2.friends)   //["tom", "jack", "mike", "single"]

登录后复制

ES5为了规范原型式的继承,有个Object.create()来方便,IE9以上可以;只是想一个对象和另一个对象保持类似的情况,完全可以这种方法

    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=Object.create(person)    person1.name="single"    person1.friends.push("singles")    var person2=Object.create(person)    console.log(person1.friends==person2.friends) //true    //Object.create()接受两个参数,一个为作为新对象原型的对象,一个为新对象定义额外属性对象    var person={        name:"double",        friends:["tom","jack","mike"]    }    var person1=Object.create(person,{         name:{             value:"single"  //每个属性都是通过自己描述符定义的         }    })

登录后复制

2、寄生式继承

思路和原型式继承一脉相承,创建一个用于封装继承过程的函数,内部通过方式增强对象,返回对象;主要考虑对象时使用

function object(o){       function F(){}       F.prototype=o       return new F()    }    function createPerson(original){       var clone=object(original)   //继承原型       clone.sayName=function(){            alert("name")       }       return clone    }    var person={       name:"double",       friends:["single","tom","jack"]    }    var person1=createPerson(person)    person1.sayName()  //name   引用类型值还是共享的

登录后复制

3、寄生组合继承

组合继承是继承中常常用到的,但是会调用两次超类型构造函数;寄生组合继承就是为了解决这个问题的

  function object(o){     function F(){}     F.prototype=o     return new F()  }  function inheritPrototype(subType,superType){     var prototype=object(superType)    //创建对象  (superType实例)     prototype.constructor=subType     //增强对象     subType.prototype=prototype      //指定对象  (原型赋予实例)  }     function SuperType(name,sex){      this.name=name      this.sex=sex      this.colors=["red"]   }   SuperType.prototype.sayName=function(){     alert(this.name)   }   function SubType(name,sex,age){      SuperType.call(this,name,sex)      this.age=age   }   inheritPrototype(SubType,SuperType)    //目前subType.prototype什么都没有   SubType.prototype.sayAge=function(){   //为subType.prototype添加个方法      alert(this.age)   }   var person1=new SubType("double","man",34)   console.log(person1.name)  //SuperType 这是个Bug   console.log(person1.sex)   //man   console.log(person1.colors) //["red"]   person1.sayAge()       //34

登录后复制

到此,差不多结束啦,感谢你对脚本之家的支持,希望我们整理的内容能够帮助到你。

相关推荐:

详解JavaScript基于面向对象之继承_javascript技巧

以上就是js面向对象之继承知识详解的详细内容,更多请关注【创想鸟】其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至253000106@qq.com举报,一经查实,本站将立刻删除。

发布者:PHP中文网,转转请注明出处:https://www.chuangxiangniao.com/p/2787525.html

(0)
上一篇 2025年3月8日 18:09:00
下一篇 2025年3月8日 18:09:10

AD推荐 黄金广告位招租... 更多推荐

相关推荐

  • JavaScript调停者模式实例详解

    本文主要和大家介绍javascript设计模式之调停者模式,详细分析了调停者模式的概念、原理、优缺点并结合javascript实例形式给出了相关使用技巧,需要的朋友可以参考下,希望能帮助到大家。 1、定义 调停者模式包装了一系列对象相互作用…

    2025年3月8日
    200
  • JavaScript求最大公共子串的方法详解

    本文主要和大家介绍javascript实现求最大公共子串的方法,涉及javascript针对字符串的遍历、匹配、运算等相关操作技巧,需要的朋友可以参考下,希望能帮助到大家。 求最大公共子串,常见的做法是使用矩阵。假设有字符串:abcdefg…

    编程技术 2025年3月8日
    200
  • Node.js实现mysql连接池使用事务自动回收连接的方法

    本文主要和大家介绍node.js实现mysql连接池使用事务自动回收连接的方法,结合实例形式分析了node.js操作mysql连接池实现基于事务的连接回收操作相关技巧,需要的朋友可以参考下,希望能帮助到大家。 本文实例讲述了Node.js实…

    编程技术 2025年3月8日
    200
  • js中delete元素和splice元素的区别详解

    本文主要和大家分享js删除数组中的元素delete和splice的区别详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧,希望能帮助到大家。 例如有一个数组是 :var textArr = [‘a’…

    编程技术 2025年3月8日
    200
  • JS删除数组里的某个元素实例代码

    本文主要为大家分享一篇js删除数组里的某个元素方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧,希望能帮助到大家。 删除数组指定的某个元素 首先可以给JS的数组对象定义一个函数,用于查找指定的元素在数组中的位置,即索引,…

    编程技术 2025年3月8日
    200
  • js中promise实例解析

    大家都知道nodejs很快,为什么会这么快呢,原因就是node采用异步回调的方式来处理需要等待的事件,使得代码会继续往下执行不用在某个地方等待着。但是也有一个不好的地方,当我们有很多回调的时候,比如这个回调执行完需要去执行下个回调,然后接着…

    2025年3月8日
    200
  • JS实现的双色球功能代码分享

    本文主要和大家介绍原生js实现的双色球功能,涉及javascript随机数生成及数值运算相关操作技巧,需要的朋友可以参考下,希望能帮助到大家。 先来看看运行效果: 具体代码如下: nbsp;html>    www.jb51.net …

    2025年3月8日
    200
  • JavaScript中六种错误类型分享

    js中的控制台的报错信息主要分为两大类,第一类是语法错误,这一类错误在预解析的过程中如果遇到,就会导致整个js文件都无法执行。另一类错误统称为异常,这一类的错误会导致在错误出现的那一行之后的代码无法执行,但在那一行之前的代码不会受到影响。 …

    编程技术 2025年3月8日
    200
  • JavaScript实现焦点进入文本框内关闭输入法代码分享

    本文主要和大家分享js实现焦点进入文本框内关闭输入法,代码简单易懂,非常不错,具有参考借鉴价值,需要的朋友参考下吧,希望能帮助到大家。 js实现焦点进入文本框内关闭输入法:imeMode 要用到的东西: imeMode:xxx 有四个参数 …

    编程技术 2025年3月8日
    200
  • JavaScript本地图片预览功能的方法

    本文主要和大家介绍javascript实现图片本地预览功能,针对非ie浏览器的html5滤镜功能及ie浏览器的相关组件功能实现不上传至服务器预览本地图片的效果,需要的朋友可以参考下,希望能帮助到大家。 实现一个在file文件域中选定图片文件…

    2025年3月8日
    200

发表回复

登录后才能评论