js继承

作者: 冷暖自知_zjz | 来源:发表于2020-01-28 12:02 被阅读0次

    1.借用构造函数

    function SuperType(){
     this.colors = ["red", "blue", "green"];
    }
    function SubType(){
     //继承了 SuperType
     //调用SuperType函数(调用父类的构造函数,此时父类中的this变为SubType),所以colors为函数SuperType 局部变量(实例变量) 每次调用都会创建一个colors
     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" 
    

    存在问题

    方法都在构造函数中定义,无法复用函数。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的。

    2.组合继承

    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 中最常用的继 承模式。而且,instanceof 和 isPrototypeOf()也能够用于识别基于组合继承创建的对象。

    缺点

    组合继承最大的 问题就是无论什么情况下,都会调用两次超类型构造函数:一次是在创建子类型原型的时候,另一次是 在子类型构造函数内部。

    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); //第二次调用 SuperType()
     this.age = age;
    }
    SubType.prototype = new SuperType(); //第一次调用 SuperType()
    SubType.prototype.constructor = SubType;//如果不改变指向 SuperType
    SubType.prototype.sayAge = function(){
     alert(this.age);
    }; 
    

    3.原型式继承

    //与Object.create()方法一样
    function object(o){
     function F(){}
     F.prototype = o;
     return new F();
    } 
    
    var person = {
     name: "Nicholas",
     friends: ["Shelby", "Court", "Van"]
    };
    var anotherPerson = object(person);
    anotherPerson.name = "Greg";
    // friends为原型上的属性 所有不同实例调用为同一个值
    anotherPerson.friends.push("Rob");
    var yetAnotherPerson = object(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    alert(person.friends); //"Shelby,Court,Van,Rob,Barbie" 
    

    这个新对象将 person 作为原型,所以它的原型中就包含一个基本类型值属性 和一个引用类型值属性。这意味着 person.friends 不仅属于 person 所有,而且也会被 anotherPerson 以及 yetAnotherPerson 共享。实际上,这就相当于又创建了 person 对象的两个副本。

    ECMAScript 5 通过新增 Object.create()方法规范化了原型式继承。这个方法接收两个参数:一 个用作新对象原型的对象和(可选的)一个为新对象定义额外属性的对象。在传入一个参数的情况下, Object.create()与 object()方法的行为相同。

    4.寄生式继承

    function createAnother(original){
     var clone = object(original); //通过调用函数创建一个新对象
     clone.sayHi = function(){ //以某种方式来增强这个对象
     alert("hi");
     };
     return clone; //返回这个对象
    } 
    

    缺点

    使用寄生式继承来为对象添加函数,会由于不能做到函数复用而降低效率;这一 点与构造函数模式类似。

    5.寄生组合式继承

    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", "green"];
    }
    SuperType.prototype.sayName = function(){
     alert(this.name);
    };
    function SubType(name, age){
     SuperType.call(this, name);
    
     this.age = age;
    }
    inheritPrototype(SubType, SuperType);
    SubType.prototype.sayAge = function(){
     alert(this.age);
    }; 
    

    相关文章

      网友评论

          本文标题:js继承

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