继承

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <script>
    // 值类型(基本类型):字符串(string)、数值(number)、布尔值(boolean)、undefined、null 
    // 引用类型:对象(Object)、数组(Array)、函数(Function)

    /* 
      原型链 继承
      问题:1.包含引用类型值的原型属性会被所有实例共享  数组(引用类型值)。
            2.在创建子类型的实例时,不能向超类型的构造函数中传递参数。
     */
    function SuperType() {
      this.property = true;
      // this.colors = ["red","black"];
    }
    SuperType.prototype.colors = ["red", "black"];
    SuperType.prototype.getSuperValue = function () {
      return this.property;
    };
    function SubType() {
      this.subproperty = false;
    }
    //继承了SuperType  原型链继承
    SubType.prototype = new SuperType();
    SubType.prototype.getSubValue = function () {
      return this.subproperty;
    };

    var instance1 = new SubType();
    var instance2 = new SubType();
    instance1.colors.push("green");
    console.log(instance1.getSuperValue()); //true
    console.log(instance1.colors);//  ["red", "black", "green"]
    console.log(instance2.colors);// ["red", "black", "green"]
    console.log(instance1);// SubType {subproperty: false}
    console.log(instance1.__proto__);// SuperType {property: true, getSubValue: ƒ}

    /*
      借用构造函数 继承  候也叫做 伪造对象 或 经典继承
      问题:方法都在构造函数中定义,因此函数复用就无从谈起了
    */
    function SuperType2(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
      this.sayName = function () {
        console.log(this.name);
      }
    }
    function SubType2() {
      //继承了SuperType 构造继承
      // this -> SubType 
      // SuperType2.call(this);
      // 传递参数
      SuperType2.call(this, "赵品霖");
    }

    //继承了SuperType 
    // SubType.prototype = new SuperType();

    var instance3 = new SubType2();
    var instance4 = new SubType2();
    instance3.colors.push("black");
    console.log(instance3.colors); // ["red", "blue", "green", "black"]
    console.log(instance4.colors); //["red", "blue", "green"]
    console.log(instance3.sayName == instance4.sayName); //false 函数无法复用
    console.log(instance3);//SubType2 {name: "赵品霖", colors: Array(4), sayName: ƒ}
    console.log(instance3.__proto__);//{constructor: ƒ}

    /* 
      组合继承
      思想:即在子类型构造函数的内部调用超类型构造函数
        instanceof 和isPrototypeOf()也能够用于识别基于组合继承创建的对象。
      
      问题:无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是在子类型构造函数内部。

      解决方法 ——寄生组合式继承。
     */
    function SuperType3(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }
    SuperType3.prototype.sayName = function () {
      console.log(this.name);
    }
    function SubType3(name, age) {
      //继承属性 构造继承
      SuperType3.call(this, name);////第二次调用SuperType()
      this.age = age;
    }
    //继承方法 原链继承
    SubType3.prototype = new SuperType3();////第一次调用SuperType()
    SubType3.prototype.constructor = SubType3;

    SubType3.prototype.sayAge = function () {
      console.log(this.age);
    };
    // 实例既分别拥有自己属性——包括colors 属性,又可以使用相同的方法了。
    var instance5 = new SubType3("aa", 20);
    var instance6 = new SubType3("bb", 21);
    instance5.colors.push("black");
    console.log(instance5.colors); // ["red", "blue", "green", "black"]
    console.log(instance6.colors); //["red", "blue", "green"]
    instance5.sayName();//aa
    instance6.sayName();//bb
    console.log(instance5.sayName == instance6.sayName); //true
    console.log(instance5); //SubType3 {name: "aa", colors: Array(4), age: 20}
    console.log(instance5.__proto__); //SuperType3 {name: undefined, colors: Array(3), constructor: ƒ, sayAge: ƒ}

    /* 
      原型式继承
        借助原型可以基于已有的对象创建新对象,同时还不必因此创建自定义类型
        Object.create(person);
        在没有必要兴师动众地创建构造函数,而只想让一个对象与另一个对象保持类似的情况下,原型式继承是完全可以胜任的。
        不过别忘了,包含引用类型值的属性始终都会共享相应的值,就像使用原型模式一样。

     */

    var person = {
      name: "Nicholas",
      friends: ["Shelby", "Court", "Van"]
    };
    // ECMAScript 5 通过新增Object.create()方法规范化了原型式继承。
    // 这个方法接收两个参数:一个用作新对象原型的对象和(可选的); 一个为新对象定义额外属性的对象
    var anotherPerson = Object.create(person);
    // 重写name
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    // var yetAnotherPerson = Object.create(person);
    // yetAnotherPerson.name = "Linda";
    // Object.create() 接受第2个参数
    var yetAnotherPerson = Object.create(person, {
      name: {
        value: "Linda"
      }
    });
    yetAnotherPerson.friends.push("Barbie");
    console.log(person.friends); //["Shelby", "Court", "Van", "Rob", "Barbie"]

    /* 
      寄生式继承:
        寄生式继承的思路与寄生构造函数和工厂模式类似.
        即创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

        在主要考虑对象而不是自定义类型和构造函数的情况下,寄生式继承也是一种有用的模式。前
     */
    function createAnother(original) {
      var clone = Object(original); //通过调用函数创建一个新对象
      clone.sayHi = function () { //以某种方式来增强这个对象
        console.log("hi");
      };
      return clone; //返回这个对象
    }
    var person = {
      name: "Nicholas",
      friends: ["Shelby", "Court", "Van"]
    };
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi(); //"hi"

    /* 
      寄生组合式继承
      所谓寄生组合式继承,即通过借用构造函数来继承属性,通过原型链的混成形式来继承方法.
      基本思路是:不必为了指定子类型的原型而调用超类型的构造函数,我们所需要的无非就是超类型原型的一个副本而已。
      本质上,就是使用寄生式继承来继承超类型的原型,然后再将结果指定给子类型的原型。

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

     */
    function inheritPrototype(subType, superType) {
      var prototype = Object(superType.prototype); //创建对象 寄生式继承来继承超类型的原型
      // 弥补因重写原型而失去的默认的constructor 属性
      prototype.constructor = subType; //增强对象
      subType.prototype = prototype; //指定对象 将结果指定给子类型的原型。
    }

    function SuperType4(name) {
      this.name = name;
      this.colors = ["red", "blue", "green"];
    }
    SuperType4.prototype.sayName = function () {
      console.log(this.name);
    };
    function SubType4(name, age) {
      SuperType4.call(this, name);
      this.age = age;
    }
    inheritPrototype(SubType4, SuperType4);
    SubType4.prototype.sayAge = function () {
      console.log(this.age);
    };
    var instance7 = new SubType4("ee", 19);
    var instance8 = new SubType4("ff", 22);
    instance7.colors.push("black");
    console.log(instance7.colors);// ["red", "blue", "green", "black"]
    console.log(instance8.colors);// ["red", "blue", "green"]
    console.log(instance7.sayName == instance8.sayName);// true
    console.log(instance7.sayAge == instance8.sayAge);// true


  </script>

</body>

</html>
寄生组合式继承 示例:

 

posted @ 2020-10-12 13:01  CHUNYIN  阅读(141)  评论(0)    收藏  举报