• JavaScript_几种继承方式(2017-07-04)


    原型链继承

    核心: 将父类的实例作为子类的原型

    //父类  
    function SuperType() {
      this.property = true;
    }
    
    SuperType.prototype.getSuperValue = function () {
      return this.property
    };
    
    //子类 
    function SubType() {
      this.subproperty = false;
    }
    
    //拿父类实例来充当子类原型对象
    SubType.prototype = new SuperType();
    
    SubType.prototype.getSubValue = function () {
      return this.subproperty
    };
    
    var instance = new SubType();
    console.log(instance.getSuperValue()); //true 

    特点:

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

    缺点:

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

    借用构造继承

    核心:使用父类的构造函数来增强子类实例,等于是复制父类的实例属性给子类(没用到原型)

    //父类 
    function SuperType() {
        this.colors = ["red", "blue"]
    }
    //子类 
    function SubType() {
        SuperType.call(this);//通过apply()和call()方法在新创建的对象上执行构造函数
    }
    
    var instance1 = new SubType();
    instance1.colors.push("black");
    console.log(instance1.colors); //["red", "blue", "black"]
    
    var instance2 = new SubType();
    console.log(instance2.colors); //["red", "blue"]

    传递参数

    //父类 
    function SuperType(name) {
        this.name = name;
    }
    //子类
    function SubType() {
        SuperType.call(this, "mnixu");//通过apply()和call()方法在新创建的对象上执行构造函数
        this.age = 20;
    }
    
    var instance1 = new SubType();
    console.log(instance1.name); //"mnixu"  
    console.log(instance1.age); //20  

    特点:

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

    缺点:

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

    组合继承(最常用的继承模式)

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

    //通过借用构造函数实现继承父类构造函数的属性(构造函数通常用this.属性,对实例对象来说私有)。
    //使用原型链实现继承父类原型的属性和方法(原型的属性和方法,对实例对象来说共享)。
    //父类
    function SuperType(name) {
        this.name = name;
        this.colors = ["red", "blue"];
    }
    
    SuperType.prototype.sayName = function() {
        console.log(this.name);
    }
    //子类
    function SubType(name, age) {
        SuperType.call(this, name);//通过apply()和call()方法在新创建的对象上执行构造函数
        this.age = age;
    }
    
    SubType.prototype = new SuperType();//拿父类实例来充当子类原型对象
    SubType.prototype.constructor = SubType;//重新生成constructor属性指向子类,模型原型对象
    SubType.prototype.sayAge = function() {
        console.log(this.age);
    };
    
    var instance1 = new SubType("mnixu", 20);
    instance1.colors.push("black");
    console.log(instance1.colors); //["red", "blue", "black"]
    instance1.sayAge(); // 20
    instance1.sayName(); // "mnixu"
    
    var instance2 = new SubType("zwj", 28);
    console.log(instance2.colors); //["red", "blue"]
    instance2.sayAge(); //28
    instance2.sayName(); //"zwj"

    特点:

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

    缺点:

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

    4.原型式继承

    借助原型并基于已有的对象创建新对象,同时还不用创建自定义类型

    //生成对象的函数
    function object(o) { //部分浏览器支持Object.create()方法
        function F() {};
        F.prototype = o;
        return new F();
    }
    
    //父类
    var Person = {
        name: "mnixu",
        color: ["blue", "black"]
    }
    //子对象1
    var anotherPerson = object(Person);
    anotherPerson.name = "Greg";
    anotherPerson.color.push("red")
    //子对象2
    var yetAnotherPerson = object(Person);
    yetAnotherPerson.name = "zwj";
    yetAnotherPerson.color.push("white")
    
    console.log(anotherPerson.color); //["blue", "black", "red", "white"]  
    console.log(yetAnotherPerson.color); //["blue", "black", "red", "white"]

    原型式继承首先在obj()函数内部创建一个临时性的构造函数 ,然后将传入的对象作为这个构造函数的原型,最后返回这个临时类型的一个新实例。

    5.寄生式继承

    这种继承方式是把原型式+工厂模式结合起来,目的是为了封装创建的过程。

    //生成对象的函数
    function object(o) { //部分浏览器支持Object.create()方法
        function F() {};
        F.prototype = o;
        return new F();
    }
    
    //生成并增强对象的函数
    function createAnother(original){  
      var clone = object(original); //通过调用函数创建一个新对象  
      clone.sayHi = function(){    //增强这个对象  
        console.log("hi")  
      };  
      return clone;           //返回这个对象  
    }  
    //父类
    var Person = {  
      name: "mnixu",  
      color: ["blue", "black"]  
    }  
     //子对象
    var anotherPerson = createAnother(Person);  
    anotherPerson.sayHi();  

    6.寄生组合式继承

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

    //生成对象的函数
    function object(o) {//部分浏览器支持Object.create()方法
        function F() {};
        F.prototype = o;
        return new F();
    }
    
    //继承原型函数
    function inheritPrototype(subType, superType) {
        var prototype = object(superType.prototype); //创建对象
        prototype.constructor = subType; //增强对象
        subType.prototype = prototype; //指定对象
    }
    //父类
    function SuperType(name) {
        this.name = name;
        this.colors = ["red", "blue"];
    }
    
    SuperType.prototype.sayName = function() {
        console.log(this.name);
    }
    //子类
    function SubType(name, age) {
        SuperType.call(this, name);
        this.age = age;
    }
    
    inheritPrototype(SubType, SuperType);
    
    SubType.prototype.sayAge = function() {
        console.log(this.age);
    };

    特点:

    1. 这个例子的高效率体现在只调用了一次SuperType构造函数,避免了在SubType.prototype上面创建不必要的属性,
      并且,原型链还能保持不变。堪称完美

    缺点:

    1. 实现较为复杂

    copy:

    重新理解JS的6种继承方式
    js高级程序设计笔记 -- 理解继承

  • 相关阅读:
    Prommetheus 插件监控 ES
    Linux LVM条带化
    MYSQL wait_timeout以及connect_timeout.这两个有什么区别
    alertmanager配置文件说明(转载)
    腾讯云MongoDB: skip查询内核优化(转载)
    MongoDB主从复制介绍和常见问题说明(转载)
    MongoDB 批量更新、批量新增、批量删除、批量替换 —— bulkWrite操作
    MongoDB Cluster 数据平衡优化
    MongoDB副本集提高读写速率
    Postgresql中时间戳与日期的相互转换(同样适用于GreenPlum)
  • 原文地址:https://www.cnblogs.com/scevecn/p/7116327.html
Copyright © 2020-2023  润新知