• 技术文章 >web前端 >js教程

    javascript中的继承方式有哪些

    VV2021-07-12 13:50:58原创151

    javascript中的继承方式有原型链继承、借用构造函数继承、组合继承、原型式继承、寄生式继承和寄生组合式继承。其中组合继承是我们平时最常用的一种继承方式。

    本文操作环境:windows10系统、javascript 1.8.5、thinkpad t480电脑。

    在javascript中如果想要继承,那么我们就必须先提供一个父类,我们这里以Person来作为父类。

    下文中所有构造函数名均无实际意义,如Coder、Rocker等,仅用于举例

    		 function Person(name){//给构造函数添加了参数
    		            this.name=name;
    		            this.sex="male";
    		            this.say=function(){
    		                console.log(this.name);
    		            }
    		        }
    		Person.prototype.age=21;//给构造函数添加了原型属性

    一、原型链继承

    		function Programmer(){
                this.name="Jayee";
            }
    
            Programmer.prototype=new Person();//子类构造函数.prototype=父类实例
    
            var per1=new Programmer();
            console.log(per1);//Programmer {name: "Jayee"}
            console.log(per1.sex);//male
            console.log(per1.age);//21
            console.log(per1 instanceof Person);//true

    重点:让新实例的原型等于父类的实例。Programmer.prototype=new Person();

    特点:实例可继承的属性有:实例的构造函数的属性,父类构造函数属性,父类原型 的 属性。(新实例不会继承父类实例的属性!)

    缺点:1、新实例无法向父类构造函数传参。

       2、继承单一。

       3、所有新实例都会共享父类实例的属性。(原型上的属性是共享的,一个实例修

        改了原型的属性(per1.__proto__.sex=“female”,则per2.sex也会变成female),另

        一个实例的原型属性也会被修改!)

    二、借用构造函数继承

            //借用构造函数继承
            function Coder(){
                Person.call(this,"Jayee");//重点:借用了Person
                this.age=18;
            }
            var cod1=new Coder();
            console.log(cod1);
            //Coder {name: "Jayee", sex: "male", hobby: "", age: 18, say: ƒ}
            console.log(cod1.name);//Jayee
            console.log(cod1.age);//18
            console.log(cod1 instanceof Person);//false

    重点:用.call()和.apply()将父类构造函数引入子类函数(在子类函数中做了父类函数的自执行(复制))

    特点:1、只继承了父类构造函数的属性,没有继承父类原型的属性。(由

        cod1.age是18而不是21可看出)

       2、解决了原型链继承缺点1、2、3。

       3、可以继承多个构造函数属性(call多个)。

       4、在子实例中可向父实例传参。

    缺点:1、只能继承父类构造函数的属性。

       2、无法实现构造函数的复用。(每次用每次都要重新调用)

       3、每个新实例都有父类构造函数的副本,臃肿。

    三、组合继承(组合原型链继承和借用构造函数继承)(常用)

            //组合继承
            function Typer(name){
                Person.call(this,name);
            }
            Typer.prototype=new Person();
            var typ=new Typer("Jayee");
            console.log(typ);
            //Typer {name: "Jayee", sex: "male", hobby: "", say: ƒ}
            console.log(typ.name);//Jayee,继承了构造函数
            console.log(typ.age);//21,继承了父类的原型的属性

    重点:结合了两种模式的优点,传参和复用

    特点:1、可以继承父类原型上的属性,可以传参,可复用。
       2、每个新实例引入的构造函数属性是私有的。

    缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那
       个父类构造函数

    四、原型式继承

            //原型式继承
            function Rocker(obj) {
            //先封装一个函数容器,用来输出对象和承载继承的原型
                function F(){}
                F.prototype=obj;//继承了传入的函数
                return new F();//返回函数对象
            }
            var per=new Person();//拿到父类实例
            var roc =Rocker(per);//F {}
            console.log(per.__proto__);//{age: 21, constructor: ƒ}
            console.log(roc.age);//21,继承了父类函数的属性

    重点:用一个函数包装一个对象,然后返回这个函数的调用,这个函数就变成了个可以随

    意增添属性的实例或对象。object.create()就是这个原理。

    特点:类似于复制一个对象,用函数来包装。

    缺点:1、所有实例都会继承原型上的属性。

       2、无法实现复用。(新实例属性都是后面添加的)

    五、寄生式继承

            //寄生式继承
            function Rocker(obj){
                function F(){}
                F.prototype=obj;//继承了传入的函数
                return new F();//返回函数对象
            }
            var per4=new Person();
            //以上是原型式继承,给原型式继承再套个壳子传递参数
            function Artist(obj){
                var roc=Rocker(obj);
                roc.name="Jayee";
                return roc;
            }
            var art = Artist(per4)
            //这个函数经过声明之后就成了可增添属性的对象
            console.log(typeof Artist);//function
            console.log(typeof art);//object
            console.log(art.name);//Jayee,返回了个roc对象,继承了roc的属性

    重点:就是给原型式继承外面套了个壳子。

    优点:没有创建自定义类型,因为只是套了个壳子返回对象(这个),这个函数顺理成章就成了创建的新对象。

    缺点:没用到原型,无法复用。

    六、寄生组合式继承(常用)

    寄生:在函数内返回对象然后调用

    组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参

             //寄生式组合式继承
    
             //寄生
             function Rocker(obj){
                function F(){}
                F.prototype=obj;//继承了传入的函数
                return new F();//返回函数对象
            }
            //Rocker就是F实例的另一种表示法
            var roc=new Rocker(Person.prototype);
            //roc实例(F实例)的原型继承了父类函数的原型
            //上述更像是原型链继承,只不过继承了原型属性
    
            //组合
            function Sub(){
                Person.call(this);
                //这个继承了父类构造函数的属性
                //解决了组合式两次调用构造函数属性的缺点
            }
            //重点
            Sub.prototype=roc;//继承了roc实例
            roc.constructor=Sub;//一定要修复实例
            var sub1=new Sub();
            //Sub的实例就继承了构造函数属性,父类实例,roc的函数属性
            console.log(sub1.age);//21

    重点:修复了组合继承的问题

    七、ES6中的Class和extends

    //todo

    相关视频教程分享:javascript视频教程

    以上就是javascript中的继承方式有哪些的详细内容,更多请关注php中文网其它相关文章!

    声明:本文原创发布php中文网,转载请注明出处,感谢您的尊重!如有疑问,请联系admin@php.cn处理
    专题推荐:javascript 继承
    上一篇:javascript怎么删除类 下一篇:javascript中的打印方法有几种
    VIP会员

    相关文章推荐

    • javascript继承有哪两种形式• javascript继承的6种方法是什么• css中有哪些属性可以继承• 分析PHP如何实现接口多继承(举例说明)

    全部评论我要评论

  • 取消发布评论发送
  • 1/1

    PHP中文网