美文网首页
四、js实现继承的几个方法

四、js实现继承的几个方法

作者: 萘小蒽 | 来源:发表于2019-03-24 02:05 被阅读0次

    1. 原型链

    原型链是实现继承的主要方法,它是利用原型,让一个引用类型继承另一个应用类型的属性和方法。

    • 实现原型链的基本模式:
    //定义父类构造函数
    function Person(){
     this.PersonImprint = "from_Person";
    }
    Person.prototype.PersonSay = function(){
        console.log(this.PersonImprint);
    }
    //定义子类构造函数
    function Son(){
      this.SonImprint = "from_Son";
    }
    //初始化子类构造函数原型为父类实例----实现继承父类属性和方法。
    Son.prototype = new Person();
    var sonExample = new Son();
    console.log(sonExample.PersonImprint)  //from_Person
    sonExample.PersonSay())                //from_Person
    console.log(sonExample.SonImprint)     //from_Son
    

    上面将Son的原型指向了Person的实例,这样Son的新原型不仅具有Person的实例所拥有的全部属性和方法,而且其原型内部还有一个指针,指向了Person的原型。
    最终得出:sonExample指向Son的原型,而Son的原型又指向Person的原型。

    //实例检测
    sonExample instanceof Son        //true
    sonExample instanceof Person   //true
    sonExample instanceof Object    //true
    //原型检测
    sonExample.prototype.isPrototypeOf(Son)   //true
    sonExample.prototype.isPrototypeOf(Person)   //true
    sonExample.prototype.isPrototypeOf(Object)   //true
    

    由于原型链的关系,可以说sonExampleSonPersonObject中任何一个类型的实例。

    • 原型链注意事项
    • 子类有时候需求覆盖超类型中的某个方法,或者添加超类型中的某个不存在的属性或方法,这种操作代码,需要放在继承(替换原型)之后。
    • 实现继承时,不能以对象字面量创建原型,这样会重写原型。
    • 原型链的问题
    • 依据原型的“共享”这一点看出的,虽然说是通过原型来实现继承,但是其原型其实是另一个类型的实例。这样原来的实例属性也就成为了现在原型的属性了。
    • 在创建子类的实例时,不能向超类的构造函数中传递参数。


    2. 借用构造函数

    这种方法的基本思想相当简单,即在子类型构造函数的内部通过call()和apply()调用超类型构造函数。

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

    上面子类的构造方法SubType“借调”了超类SuperType的构造函数,在创建新的实例过程中,运行了超类构造函数,这样一来子类就拥有了超类函数中定义的所有属性了。

    • 传递参数
    function SuperType(name){
       this.name = name;
    }
    function SubType(){
       SuperType.call(this,"余嘉")
    }
    var instance1 = new SubType()
    
    • 借用构造函数的弊端
    • 如果是仅仅借用构造函数(超类),那么构造函数(超类)的存在意义就是问题所在,因为方法都在超类中定义,因此构造函数的复用就无从谈起了。
    • 超类中给原型定义的方法,对于子类型而言是看不见的。

    3. 组合继承(原型链+借用构造函数)

    原型链借用构造函数组合使用,利用两者的长处。

    function superType(name){
       this.name = name;
       this.colors =  ["red","blue","green"];
    }
    superType.prototype.sayName = function(){
       console.log(this.name)
    }
    funtionc subType(name,age){
       superType.call(this,name);
       this.age = age;
    }
    subType.prototype = new superType();
    subType.prototype.constructor = subType;
    subType.prototype.sayAge = function(){
        console.log(this.age)
    };
    var instance1 = new subType("余嘉",27);
    //subType {name: "余嘉", colors: Array(3), age: 27};
    instance1.sayAge()  //   27
    instance1.sayName()  //   "余嘉"
    

    组合继承避免了原型链和借用构造模式的缺陷,融合了他们的优点,是项目中最常用的继承模式。

    4. 原型式继承(Object.create( obj , newKeyobj)

    借助原型可以基于已有的对象(实例)创建新对象,同事还不必因此创建自定义类型。

    function create(0){
        function F(){}
        F.prototype = o;
        return new F();
    }
    

    create()函数内部,先创建一个临时性的构造函数,然后将传入的对象O作为这个构造函数的原型(浅复制),然后返回临时构造的实例。

    es5新增的Object.create(obj , newKeyobj)规范这个原型式继承,它接受两个参数

    • (必须的)obj 作为新对象的原型对象
    • (可选的)为新对象定义额外属性对象,和Object.difineProperties()方法的参数一样。
    var person = {
        name : "余嘉",
        friends:["cat","dog"]
    }
    var otherPerson1 = Object.create(person);
    otherPerson1.name = "小微";
    otherPerson1.friends.push("萝卜");
    var otherPerson2 = Object.create(person);
    otherPerson1.name = "达令";
    otherPerson1.friends.push("白菜");
    console.log(person.friends);
    //["cat","dog","萝卜","白菜"]
    
    var person = {
        name : "余嘉",
        friends:["cat","dog"]
    }
    var otherPerson1 = Object.create(person,{
         name:{
          value:"小微"
         }
    });
    
    • “共享”的利与弊,永远是原型模式的烙印。

    5. 寄生式继承

    寄生式继承的思路与寄生构造函数和工厂模式类似,创建一个经用于封装继承过程的函数。

    function createAnother(original){
      var clone  = Object(original);
      clone.sayHi = function(){
          console.log("Hi")    
       };
      return clone
     }
    

    调用

    var person = {
      name:"余嘉",
      friends:["Shelby", "Court", "Van"] 
    }
    var anotherPerson = createAnother(person);
    anotherPerson.sayHi();
    //Hi
    

    相关文章

      网友评论

          本文标题:四、js实现继承的几个方法

          本文链接:https://www.haomeiwen.com/subject/sqcjvqtx.html