• JavaScript之原型式继承&寄生式继承和寄生组合式继承以及优缺点


    一.原型式继承

    1.这种方法并没有使用严格意义上的构造函数,借助原型可以基于已有的对象创建新的对象

    function object(o) {
      function F() {}
      F.prototype = o;
      return new F();
    }
    // 在object()函数内部,先创建一个临时性的构造函数,然后将传入的对象作为这个构造函数原型,最后返回了这个临时类型的一个新实例.
    // object()本质上对其中传入的对象进行了一次浅复制
    // 看如下的例子:
    var person = {
      name: "kebi",
      friends: ["kuli", "hadeng"]
    };
    var onePerson = object(person);
    onePerson.name = "heyushuo";
    onePerson.friends.push("heyushuo");
    var twoPerson = object(person);
    twoPerson.name = "yaoming";
    twoPerson.friends.push("yaoming");
    
    //这里打印
    console.log(twoPerson); //['kuli','hadeng','heyushuo','yaoming']
    

    缺点: 包含引用类型的属性值始终都会共享相应的值,和原型链继承一样。

    2.ES5 通过新增 Object.create()方法规范化了原型式继承,此方法可以接受两个参数,第一个参数最为新对象原型的对象 和一个为新对象定义额外属性的对象.

    var person = {
      name: "kebi",
      friends: ["kuli", "hadeng"]
    };
    var onePerson = Object.create(person, {
      name: "heyushuo"
    });
    onePerson.friends.push("heyushuo");
    var twoPerson = Object.create(person, {
      name: "yaoming"
    });
    twoPerson.friends.push("yaoming");
    //这里打印
    console.log(twoPerson); //['kuli','hadeng','heyushuo','yaoming']
    // 主:在没有必要创建构造函数,而是指向让一个对象与另外一个对象保持类似的情况下,原型式继承完全可以胜任
    

    二.寄生式继承

    创建一个仅用于封装继承过程的函数,该函数在内部以某种形式来做增强对象,最后返回对象。

    function createAnother(original) {
      var clone = object(original); // 通过调用 object() 函数创建一个新对象
      clone.sayHi = function() {
        // 以某种方式来增强对象
        console.log("hi");
      };
      return clone; // 返回这个对象
    }
    // 函数的主要作用是为构造函数新增属性和方法,以增强函数
    var person = {
      name: "Nicholas",
      friends: ["Shelby", "Court", "Van"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); //"hi"```
    

    缺点:

    1. 原型继承存在的缺点他都存在
    2. 使用寄生式继承为对象添加方法,会由于不能做到方法的复用而降低效率,这一点和构造函数模式类似

    三.寄生组合式继承

    寄生组合式继承, 即通过借用构造函数来继承属性, 在原型上添加共用的方法, 通过寄生式实现继承.

    //寄生式继承的基本模式
    function inheritPrototype(subType, superType) {
      var prototype = Object.create(superType.prototype); // 创建对象,创建父类原型的一个副本
      prototype.constructor = subType; // 增强对象,弥补因重写原型而失去的默认的constructor 属性
      subType.prototype = prototype; // 指定对象,将新创建的对象赋值给子类的原型
    }
    
    // 父类初始化实例属性和原型的属性和方法
    function SuperType(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }
    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);
    };
    
    var instance1 = new SubType("heyushuo");
    var instance2 = new SubType("kebi");
    instance1.sayName(); //heyushuo
    instance2.sayName(); //kebi
    instance1.colors.push("yellow"); // ["red", "blue", "green", "yellow"]
    instance1.colors.push("black"); // ["red", "blue", "green", "black"]
    

    总结:

    上边的例子高效的体现了只调用了一次 SuperType 构造函数,并且因此也避免了在 SubType.prototype 上面创建不必要的 多余的属性.与此同时,原型链还能保持不变

  • 相关阅读:
    了解xss
    kail Windows10 远程连接解决办法
    信息收集二级域名或ip收集
    mpvue引用Echarts不渲染问题
    IIS状态码
    apicloud的tapmode用法
    JavaScript交换两个变量值的七种解决方案
    IIS express 服务的开启, 支持多个iis express
    asp.net解决跨域访问问题
    Flex 布局
  • 原文地址:https://www.cnblogs.com/heyushuo/p/10057676.html
Copyright © 2020-2023  润新知