JavaScript 如何实现继承?

1.原型链继承

function Parent () {
	this.name = '风驰电掣布狼牙';
}
Parent.prototype.getName = function () {
    console.log(this.name);
}
function Child () {}
Child.prototype = new Parent();
var child = new Child();
console.log(child.getName()) // 风驰电掣布狼牙

特点:

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

缺点:

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

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对构造函数的数组做修改是不会影响到其他的实例,
    //因为它改的是属于它自己的那一份,不像原型那样大家共享
 
    //------------------------//

 1. List item

    function a3(name) { 
    	this.name=name; 
    }
    function b3() {
    	a3.call(this,"琪亚娜·卡斯兰娜");this.age=16;  
    }
    var instance4=new b3();
    console.log(instance4.name);//琪亚娜·卡斯兰娜
    console.log(instance4.age);//16
    //这个例子说明构造函数继承可以传参数

特点:

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

缺点:

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

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("重装小兔19C",12);
    instance5.color.push(5);
    console.log(instance5.color);//[1, 2, 3, 4, 5]
    instance5.sayAge();//12
    instance5.sayName();//重装小兔19C
 
 
    var instance6=new b4("布狼牙",22);
    console.log(instance6.color);//[1, 2, 3, 4]
    instance6.sayName();//布狼牙
    instance6.sayAge()//22
    var instance5=new a4("重装小兔19C");
    instance5.sayAge();// not  a  function
    //这个输出说明b4.prototype=new a4(),然后b4.prototype.sayAge增加了prototype的方法,但是 
    //增加的方法并没有增加到a4上面

特点:

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

缺点:

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

4.原型式继承

	 function object(o){
        function F(){};
        F.prototype=o;
        return new F();
    }
 
    var person={name:"卡莲·卡斯兰娜",age:[1,2,3]};
    var anp=object(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:"卡莲·卡斯兰娜",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.sayHi=function(){  //扩充了方法
         console.log("樱花~~散!");
     };
     return clone;
   }
   var per={name:"八重嘤",age:[1,2,3]};
   var pp=createAnother(per);
   pp.sayHi();

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

6.寄生组合式继承

	 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("白骑士·月光",99);
    instance7.sayName();

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

在这里插入图片描述
特点:

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

缺点:代码比较复杂

参考文档:JS继承的实现方式
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值