JavaScript继承

本文详细介绍了JavaScript中的六种继承方式:原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承和寄生组合式继承,包括它们的特点、优缺点和应用场景。其中,寄生组合继承被认为是引用类型最理想的继承范式,但其代码相对复杂。
摘要由CSDN通过智能技术生成

1.原型链继承

function Parent () {this.name = 'aa';}
 
Parent.prototype.getName = function () {
 
    console.log(this.name);
 
}
 
function Child () {}
 
Child.prototype = new Parent();
 
var child = new Child();
 
console.log(child.getName()) // aa

特点:

  • 非常纯粹的继承关系,实例是子类的实例,也是父类的实例
  • 父类新增原型方法/原型属性,子类都能访问到
  • 简单,易于实现

缺点:

  • 要想为子类新增属性和方法,必须要在new Child()这样的语句之后执行,不能放到构造器中
  • 无法实现多继承
    来自原型对象的引用属性被所有实例共享
    创建子类实例时,无法向父类构造函数传参

2.构造函数继承

function a2() {this.color=[1,2,3,4];  }
 
function b2() {a2.call(this);  }
 
 
var instance2=new b2();
 
instance2.color.push(5);
 
console.log(instance2.color);//[1, 2, 3, 4, 5]
 
 
var instance3=new b2();
 
console.log(instance3.color);//[1, 2, 3, 4]
 
//上面两个例子主要想指出,instance2对构造函数的数组做修改是不会影响到其他的实例,
//因为它改的是属于它自己的那一份,不像原型那样大家共享
 
 
//------------------------//
 
 
function a3(name) { this.name=name; }
 
 
function b3() {a3.call(this,"ww");this.age=29;  }
 
 
var instance4=new b3();
 
console.log(instance4.name);//ww
 
console.log(instance4.age);//29
 
//这个例子说明构造函数继承可以传参数

特点:

  • 解决了原型链继承中,子类实例共享父类引用属性的问题
  • 创建子类实例时,可以向父类传递参数
  • 可以实现多继承(call多个父类对象)

缺点:

  • 实例并不是父类的实例,只是子类的实例
  • 只能继承父类的实例属性和方法,不能继承原型属性/方法
  • 无法实现函数复用,每个子类都有父类实例函数的副本,影响性能

3.组合继承

function a4(name) {this.name=name;this.color=[1,2,3,4];  }
 
a4.prototype.sayName=function(){console.log(this.name);}
 
 
function b4(name,age) { a4.call(this,name);this.age=age; }
 
b4.prototype=new a4();
 
b4.prototype.constructor=b4;
 
b4.prototype.sayAge=function(){console.log(this.age);}
 
 
var instance5=new b4("aa",12);
 
instance5.color.push(5);
 
console.log(instance5.color);//[1, 2, 3, 4, 5]
 
instance5.sayAge();//12
 
instance5.sayName();//aa
 
 
var instance6=new b4("bb",22);
 
console.log(instance6.color);//[1, 2, 3, 4]
 
instance6.sayName();//bb
 
instance6.sayAge()//22
 
 
var instance5=new a4("aa");
 
instance5.sayAge();// not  a  function
//这个输出说明b4.prototype=new a4(),然后b4.prototype.sayAge增加了prototype的方法,但是 
//增加的方法并没有增加到a4上面

特点:

  • 弥补了构造继承的缺陷,可以继承实例属性/方法,也可以继承原型属性/方法
  • 既是子类的实例,也是父类的实例
  • 不存在引用属性共享问题
  • 可传参
  • 函数可复用

缺点:

调用了两次父类构造函数,生成了两份实例(子类实例将子类原型上的那份屏蔽了)

4.原型式继承

   //object的结果的_proto_=o
   function object(o){
 
        function F(){};
 
        F.prototype=o;
 
        return new F();
 
    }
 
 
    var person={name:"wwwwwww",age:[1,2,3]};
 
 
    var anp=object(person);//anp._proto_=person
 
    anp.name="er";
 
    anp.age.push(99);
 
 
    var ynp=object(person);
 
    ynp.name="ll";
 
    ynp.age.push(100);
 
 
    console.log(person.age);//[1, 2, 3, 99, 100]
    //输出结果说明属性共享这一问题
 
 
    //----------------//
 
    var person2={name:"wwwwwww",age:[1,2,3]};
 
 
    var anp=Object.create(person2);
 
    anp.name="er";
 
    anp.age.push(99);
 
 
    var ynp=Object.create(person2);
 
    ynp.name="ll";
 
    ynp.age.push(100);
 
 
    console.log(person2.age);//[1, 2, 3, 99, 100]
    //这里说明用create方法一样可以完成原型式继承

缺点也是来自原型对象的引用属性被所有实例共享

5.寄生式继承

 function createAnother(original) {
 
        var clone=object(original);//clone._proto_=original
 
        clone.sayHi=function(){  //扩充了方法
 
            console.log("hi");
 
        };
 
        return clone;
 
      }
 
 
      var per={name:"loud",age:[1,2,3]};
 
      var pp=createAnother(per);
 
      pp.sayHi();

缺点和构造函数继承一样,都是每次创建对象都会创建一遍方法,内存占用大

6.寄生组合式继承

  //inheritPrototype执行的结果是b5.prototype._proto=a5.prototype,b5.prototype.constructor=b5
 
   function inheritPrototype(b5,a5) {
 
        var prototype=object(a5.prototype);
 
        prototype.constructor=b5;
 
        b5.prototype=prototype;
 
     }
 
 
     function a5(name) {
 
         this.name=name;
 
         this.color=[1,2,3];
 
     }
 
 
     a5.prototype.sayName=function(){
 
         console.log(this.name);
 
     }
 
 
     function b5(name,age) {
 
         a5.call(this,name);
 
         this.age=age;
 
    }
 
 
    inheritPrototype(b5,a5);
 
 
    b5.prototype.sayAge=function(){
 
       console.log(this.age);
 
    }
 
 
    var instance7=new b5("dd",99);
 
    instance7.sayName();

其实寄生组合继承我觉得可以理解为组合继承的改进,和组合继承相比,避免了new a5()的写法,同时又保持了原型继承关系

特点:

只调用了一次构造函数,并且避免了在 prototype 上面创建不必要的、多余的属性。与此同时,原型链还能保持不变;因此,还能够正常使用 instanceof 和 isPrototypeOf。开发人员普遍认为寄生组合式继承是引用类型最理想的继承范式。

缺点:代码比较复杂

参考文档:JS继承的实现方式
————————————————
版权声明:本文为CSDN博主「小幽艾」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/loisandyu/article/details/83046950

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值