zoukankan      html  css  js  c++  java
  • JS继承几种方式

    一 原型链继承:核心: 将父类的实例作为子类的原型(父类子类都是构造函数,通过类创建对象)

    • 优点:方法复用
      方法定义在父类的原型上,可以复用父类构造函数的方法,比如say方法。
    • 缺点:
      • 创建子类实例时,无法传父类参数
      • 子类实例共享
      • 继承单一,无法实现多继承(在JavaScript中继承是依赖于原型prototype链实现的,只有一条原型链,理论上是不支持继承多个父类的,可以通过变通的方式实现类似功能)
     1     function SuperType(){
     2         this.property=true;
     3     }
     4     SuperType.prototype.getSuperValue=function(){
     5         return this.property;
     6     };
     7     function SubType(){
     8         this.subproperty=false;
     9     }
    10     //继承了SuperType
    11     SubType.prototype=new SuperType();
    12 
    13     SubType.prototype.getSubValue=function(){
    14         return this.subproperty;
    15     };
    16     var instance=new SubType();
    17     console.log(instance.getSuperValue());  //true

    二 构造函数继承:核心:借用父类构造函数来增强子类实例,等于是复制父类的实例属性给子类

    优点:实例之间独立

    • 创建子类实例,可以向父类构造函数传参
    • 子类实例不共享父类构造函数的引用属性,如arr
    • 可实现多继承(通过多个call或apply继承多个父类)

    缺点:

    • 父类方法不能复用
    • 由于方法在父构造函数中定义,导致方法不能复用(每次创建子类实例都要创建一遍方法)
    • 子类实例继承不了父类原型上的属性,因为没有用到原型
     1 function Parent(name){
     2     this.name = name;    //实例基本属性(该属性,强调私有,不共享)
     3     this.arr = [1];    (该属性,强调私有)
     4     this.say = function(){    //实例引用属性(该属性,强调复用,需要共享)
     5         console.log('hello);
     6     }
     7 }
     8 function Child(name,like){
     9     Parent.call(this,name);    //核心,拷贝了父类的实例属性和方法
    10     this.like = like;
    11 }
    12 let boy1 = new Child('小刚','apple');
    13 let boy2 = new Child('小明','orange');
    14 
    15 //优点1:可向父类构造函数传参
    16 console.log(boy1.name,boy2.name);    //小刚,小明
    17 //优点2:不共享父类构造函数的引用属性
    18 boy1.arr.push(2);
    19 console.log(boy1.arr,boy2.arr);    //[1,2],[1]
    20 
    21 //缺点1:方法不能复用
    22 console.log(boy1.say === boy2.say);    //false (说明boy1和boy2的say方法独立,不是共享的)
    23 
    24 //缺点2:不能继承父类原型上的方法
    25 Parent.prototype.walk = function(){
    26     console.log('我会走路');
    27 }
    28 boy1.walk;    //undefined(说明实例不能获得父类原型上的方法)

    三 拷贝继承:

    四 组合继承:核心:通过调用父类构造,继承父类的属性并保留传参的优点,然后通过原型链继承将父类实例作为子类原型,实现函数复用

    优点:

    1. 父类的方法定义在原型对象上,可以实现方法复用
    2. 创建子类实例,可以向父类构造函数传参;并且不共享父类的引用属性,如arr

    缺点:由于调用了2次父类的构造方法,会存在一份多余的父类实例属性

    五 原型式继承:

    缺点:引用类型值会共享,值类型不会共享,因此在改变值类型时,相当于给自己添加了属性。

     function object(o){
        function F(){}
        //F.prototype={name:'ccdida',friends:['shelly','Bob']}
        F.prototype=o
        // new F() 
        //F是个构造函数,返回F的实例:1.this此时用不上 2.将实例的__proto__指向F.prototype.
        //即返回了一个实例,其__proto__指向{name:'ccdida',friends:['shelly','Bob']}
        return new F()
      }
      var person={
        name:'ccdida',
        friends:['shelly','Bob']
      }
      var person1=object(person)
      var person2=object(person)
      //object函数相当于实现了Object.Create的功能
      console.log(person1.__proto__===person) //true 
      person2.friends.push('shlimy')
      console.log(person1.friends)// ["shelly", "Bob", "shlimy"]

     

    六 寄生组合继承:核心:通过寄生方式,砍掉父类的实例属性,这样,在调用两次父类的构造的时候,就不会初始化两次实例方法/属性,避免的组合继承的缺点 

     1  function Parent(name) {
     2     this.name = name;    //实例基本属性(该属性,强调私有,不共享)
     3     this.arr = [1];        //实例引用属性(该属性,强调私用,不共享)
     4   }
     5   Parent.prototype.say = function () {    //将需要复用、共享的方法定义在父类原型上
     6     console.log('hello');
     7   }
     8   function Child(name, like) {
     9     Parent.call(this, name);    //核心
    10     this.like = like;
    11   }
    12   //核心 通过创建中间对象,子类原型和父类原型就会隔离开,不再是同一个,有效避免了方式4的缺点
    13   Child.prototype = Object.create(Parent.prototype);
    14 
    15   Child.prototype.constructor = Child;//修复代码
    16 
    17   let boy1 = new Child('小刚', 'apple');
    18   let boy2 = new Child('小明', 'orange');
    19   let p1 = new Parent('小爸爸');
    20 
    21   console.log(boy1.constructor, p1.constructor);    //修复之后:Child,Parent
    22 
    23 
    24   // Object.create()函数等价为:下面函数即是原型式继承实现
    25   function object(o) {
    26     function F() { }
    27     F.prototype = o;
    28     return new F();
    29   }
    30 
    31   // 于是中间那段核心代码可改为:
    32   function object(o) {
    33     function F() { }
    34     F.prototype = o;
    35     return new F();
    36   }
    37   Child.prototype = object(Parent);
    38 
    39   Child.prototype.constructor = Child;

    JS继承的实现方式:https://www.cnblogs.com/humin/p/4556820.html

    JS五种继承方法和优缺点:https://blog.csdn.net/m0_51235736/article/details/113795449 

    寄生组合式继承:https://segmentfault.com/a/1190000037433122 

    ES6中extends类继承实现原理 

  • 相关阅读:
    基于矩阵式产品管理的奖金如何发放?
    再谈技术开发项目与产品开发项目的差异
    如何培养合格的产品经理?
    技术规划变革管理——共创力典型咨询案例
    研发人员任职资格管理深圳公开课成功举办!
    深圳市共创力《产品需求挖掘和规划》深圳公开课!(2019.12.6~7)
    技术规划与路标开发实践公开课在深圳成功举办!
    产品路标开发是企业持续成功的关键路径
    什么是技术规划(TPP)?
    什么是测试系统工程师(TSE)?
  • 原文地址:https://www.cnblogs.com/terrymin/p/14630479.html
Copyright © 2011-2022 走看看