• 原型链继承/借用构造函数继承/组合继承/class继承


    关于继承有很多方式,这里着重讲一下原型链继承/借用构造函数继承/组合继承以及各自的优缺点

    1.原型链继承:子类型的原型对象 = 超类型的实例

    function SuperType() {
        this.colors = ["red", "blue", "green"];
    }
    function SubType() {
    }
    //继承了 SuperType 
    SubType.prototype = new SuperType();
    var instance1 = new SubType();
    instance1.colors.push("black");
    alert(instance1.colors); //"red,blue,green,black" 
    var instance2 = new SubType();
    alert(instance2.colors); //"red,blue,green,black"

    问题:

      a.由于包含引用类型值的原型属性会被所有实例共享,而字符串型、数值型则不被共享,所以对 instance1.colors 的修改,instance2.colors 也会被修改;基本类型没有这个问题:

    function SuperType(){ 
     this.color = "red";
    } 
    function SubType(){ 
    } 
    //继承了 SuperType
    SubType.prototype = new SuperType(); 
    var instance1 = new SubType(); 
    instance1.color = "black"; 
    alert(instance1.color); //black
    var instance2 = new SubType(); 
    alert(instance2.color); //red

      b.在创建子类型的实例时,不能向超类型的构造函数中传递参数

    2.借用构造函数:通过使用 apply()和 call()方法也可以在(将来)新创建的对象上执行构造函数

    function SuperType(){ 
     this.colors = ["red", "blue", "green"]; 
    } 
    function SubType(){ 
     //继承了 SuperType 
     SuperType.call(this); 
    } 
    var instance1 = new SubType(); 
    instance1.colors.push("black"); 
    alert(instance1.colors); //"red,blue,green,black" 
    var instance2 = new SubType(); 
    alert(instance2.colors); //"red,blue,green"
    通过使用 call()方法(或 apply()方法也可以),我们实际上是在(未来将要)新创建的 SubType 实例的环境下调用了 SuperType 构造函数。这样一来,就会在新 SubType 对象上执行 SuperType()函数中定义的所有对象初始化代码。结果,SubType 的每个实例就都会具有自己的 colors 属性的副本了。

    问题:如果仅仅是借用构造函数,那么也将无法避免构造函数模式存在的问题——方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。考虑到这些问题,借用构造函数的技术也是很少单独使用的。

    3.组合继承:指的是将原型链和借用构造函数的技术组合到一块,从而发挥二者之长的一种继承模式。其背后的思路是使用原型链实现对原型属性和方法的继承,而通过借用构造函数来实现对实例属性的继承。

    function SuperType(name){ 
     this.name = name; 
     this.colors = ["red", "blue", "green"]; 
    } 
    SuperType.prototype.sayName = function(){ 
     alert(this.name);
    }; 
    function SubType(name, age){ 
     //继承属性
     SuperType.call(this, name); 
     this.age = age; 
    } 
    //继承方法
    SubType.prototype = new SuperType(); 
    SubType.prototype.constructor = SubType; 
    SubType.prototype.sayAge = function(){ 
     alert(this.age); 
    }; 
    var instance1 = new SubType("Nicholas", 29); 
    instance1.colors.push("black"); 
    alert(instance1.colors); //"red,blue,green,black" 
    instance1.sayName(); //"Nicholas"; 
    instance1.sayAge(); //29 
    var instance2 = new SubType("Greg", 27); 
    alert(instance2.colors); //"red,blue,green" 
    instance2.sayName(); //"Greg"; 
    instance2.sayAge(); //27
    组合继承避免了原型链和借用构造函数的缺陷,融合了它们的优点,成为 JavaScript 中最常用的继承模式

    因此,使用继承时优先使用组合继承

    4. class继承

    在 ES6 中,我们可以使用 class 去实现继承,并且实现起来很简单

     1 class Parent {
     2   constructor(value) {
     3     this.val = value
     4   }
     5   getValue() {
     6     console.log(this.val)
     7   }
     8 }
     9 class Child extends Parent {
    10   constructor(value) {
    11     super(value)
    12     this.val = value
    13   }
    14 }
    15 let child = new Child(1)
    16 child.getValue() // 1
    17 child instanceof Parent // true

    class 实现继承的核心在于使用 extends 表明继承自哪个父类,并且在子类构造函数中必须调用 super,因为这段代码可以看成 Parent.call(this, value)

    当然了,之前也说了在 JS 中并不存在类,class 的本质就是函数。

  • 相关阅读:
    ngnix-内网能用,外网不能用
    python学习
    mysql数据库导出xls-自定义
    Oralce-资源配置PROFILE
    oracle-用户管理与权限分配
    Oracle-创建索引分区
    Oracle-表分区
    Oracle--索引视图序列等对象
    Oracle-数据表对象
    Oracle-管理表空间和数据文件
  • 原文地址:https://www.cnblogs.com/anu0823/p/12745527.html
Copyright © 2020-2023  润新知