JS中几种继承的方式及缺点

JS中几种继承的方式及缺点

原型链继承
每个构造函数都有一个原型对象(通过prototype属性)
原型对象都包含一个指向构造函数的指针(通过constructor属性)
实例都包含一个指向原型对象的内部指针(通过隐式proto属性)
那么,若原型对象等于另一个原型的实例,则此时原型对象将包含一个指向另一个原型对象的指针。相应的另一个原型中也包含一个指向另一个构造函数的指针。如此层层递进,就构成了实例与原型的链条。

//父类
 function Person(name){
            this.name=name;
            this.sum=function(){
                console.log(this.name)
            }
        }
        Person.prototype.age=10;
//原型链继承
function people(){
           this.name='NAME';
       }
       people.prototype=new Person();
       var people1=new people();
       console.log(people1.age);
       console.log(people1 instanceof Person);

缺点:

  1. 新实例无法向父类构造函数传参。
  2. 继承单一。
  3. 原型上的属性是共享的,一个实例修改了原型属性,另一个实例的原型属性也会被修改。
    构造函数继承
    构造函数继承也叫伪造对象或经典继承,这种方式解决了原型链继承的问题,实例可以独享一份引用类型的值 ,通过call改变this指向,这样每次执行SuperType函数,this指向的都是新的对象。相当于每个新的对象都有一份完整的SuperType代码。即每个实例都有一份自己的colors属性副本。可以通过call函数向SuperType传参数。
//构造函数继承
 function people(){
           Person.call(this,'NAME');
           this.age=12;
       }
       var people1=new people();
       console.log(people1.name);
       console.log(people1.age);
       console.log(people1.instanceof Peerson);

缺点:只能继承父类构造函数的属性,无法实现构造函数的复用,每个新实例都有父类构造函数的副本,臃肿。
组合继承
也叫伪经典继承,它是最常用的的继承方式,组合继承将原型链继承和构造函数继承结合到一起,结合了两种模式的优点,传参和复用。

//组合继承
    function people(name){
        Person.call(this,name);
    }
    people.prototype=new Person();
    var peo=new people('NAME');
    console.log(peo.name);
    console.log(peo.age);

缺点:调用了两次父类构造函数(耗内存),子类的构造函数会代替原型上的那个父类构造函数。
原型式继承
借助原型可以基于已有的对象创建新对象,不必因此创建自定义类型。该方法与原型链继承类似,但是写法比它简单,若只是想让一个对象和另一个相似,可以使用这种方法。

//原型式继承
    function people(obj){
        function P(){}
        P.prototype=obj;
        return new P();
    }
    var peo=new Person();
    var peo1=content(peo);
    console.log(peo1.age);

缺点:包含引用类型值的属性始终共享相应的值。无法实现复用。
寄生式继承
没有创建自定义类型,因为只是套了个壳子返回对象,这个函数顺理成章就成了创建的新对象。

 //寄生式继承
    function content(obj){
        function P(){}
        P.prototype=obj;
        return new P();
    }
    var sup=new Person();
    function subobject(obj){
        var sub=content(obj);
        sub.name='gar';
        return sub;
    }
    var sup2=subobject(sup);
    console.log(typeof subobject);
    console.log(typeof sup2);
    console.log(sup2.name);

缺点:这样做相当于构造函数那样,并不是真正的函数复用。而且包含引用类型值的属性依然始终共享相应的值。
寄生组合式继承
寄生:在函数内返回对象然后调用。
组合:1、函数的原型等于另一个实例。2、在函数中用apply或者call引入另一个构造函数,可传参。
重点:修复了组合继承的问题。

//寄生
    function content(obj){
        function P(){}
        P.prototype=obj;
        return new P();
    }
    var con=content(Person.prototype);
    //组合
    function Sub(){
        Person.call(this);
    }
    Sub.prototype=con;
    con.constructor=Sub;
    var sub1=new Sub();
    console.log(sub1.age);

猜你喜欢

转载自blog.csdn.net/weixin_44260504/article/details/89882888