美文网首页
基于javascript的对象继承

基于javascript的对象继承

作者: 陆霁 | 来源:发表于2018-01-23 17:29 被阅读6次

    谈到继承,javascript在ES6出现之前,是不提供原生的继承机制的,这里我们将通过几种方法,来实现功能上的继承。

    1.基于原型链的继承

    function SuperType(){
        this.colors=["red", "blue", "green"]
    }
    SuperType.prototype.getSuperValue = function(){
        return this.property;
    }
    function SubType(){
    }
    SubType.prototype = new SuperType();
    SubType.prototype.getSuperValue = function(){
        return this.subproperty;
    }
    SubType.prototype.getSuperValue = function(){
        return false;
    }
    var instance1 = new SubType();
    instance1.colors.push("black");
    var instance2 = new SubType();
    console.info(instance2.colors)
    
    result:  [ 'red', 'blue', 'green', 'black' ]
    console.info(instance1.hasOwnProperty("colors"), "colors" in instance1)
    result: false true           //说明colors这个属性不是子类的实例属性,而是原型属性
    

    着重看第9行,子类的原型指向父类的实例,同样也就继承了父类实例后的所有属性,追着父类实例的原型链走,同样也继承到了父类的方法。

    缺点:虽然得到了父类的属性和方法,但是都是在原型上的,当某一个实例对其属性进行更改时,会直接反应到原型上,如果这时实例化另外一个实例的话,就将接受这种更改,这往往是不能接受的,这在倒数。


    2.借用构造函数来实现继承

    function SuperType(){
        this.colors=["red", "blue", "green"]
    }
    function SubType(){
       SuperType.call(this);
    }
    var instance1 = new SubType();
    instance1.colors.push("black");
    console.info(instance1.colors)  //red, blue, green, black
    
    var instance2 = new SubType();
    console.info(instance2.colors)  //red, blue, green
    
    console.info(instance1.hasOwnProperty("colors"), "colors" in instance1)
    result: true true
    

    着重看第五行,用了构造函数的call方法, call方法作用在与改变函数执行的作用域,第五行传入的this.也就是子类运行时的作用域,我们把子类作用域传入父类作用域,导致父类定义的那些属性会直接挂载到子类的作用域里,这个时候我们对子类进行实例化后得到的属性为实例属性。这个时候对各种对属性进行操作就不会影响到其他实例了。

    缺点:如果方法也按照借用构造函数进行继承的话,那么方法他在每一个实例都会有一个拷贝,显然如果每个实例方法都是一样的话,会造成大量资源的浪费。


    3.组合继承

    组合继承: 我们把想要继承的属性通过借用构造函数的方法,把方法通过原型链进行继承。

    function SuperType(name){
        this.name = name;
        this.colors=["red", "blue", "green"]
    }
    SuperType.prototype.sayName = function(){
        console.info(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(){
        console.info(this.age);
    }
    
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    console.info(instance1.colors)  //red, blue, green, black
    instance1.sayName();  //"Nicholas"
    instance1.sayAge()    //29
    var instance2 = new SubType("Greg", 27);
    console.info(instance2.colors) //red, blue, green
    instance2.sayName()  //"Greg"
    instance2.sayAge()   //27
    

    但是细心的你会发现我们在借用原型链实现方法的继承时,不仅把父类的方法挂载到原型上,父类的属性也挂载到了原型上,但是我们也借用构造函数实现实例属性的继承,而原则上是不需要挂载属性的,这就造成了原型上属性的冗余。

    那么如何规避这种冗余呢?

    function SuperType(name){
        this.name = name;
        this.colors=["red", "blue", "green"]
    }
    SuperType.prototype.sayName = function(){
        console.info(this.name);
    }
    //借用构造函数完成属性的继承
    function SubType(name, age){
        SuperType.call(this, name); //添加公共属性
        this.age = age;  //添加自有属性
    }
    //借用原型链实现方法的继承
    function F(){}
    //这样就只继承到了父类原型上的方法。
    F.prototype = SuperType.prototype;
    SubType.prototype = new F();
    
    // SubType.prototype = new SuperType();
    SubType.prototype.constructor = SubType;
    SubType.prototype.sayAge = function(){
        console.info(this.age);
    }
    
    var instance1 = new SubType("Nicholas", 29);
    instance1.colors.push("black");
    console.info(instance1.colors)  //red, blue, green, black
    instance1.sayName();  //"Nicholas"
    instance1.sayAge()    //29
    var instance2 = new SubType("Greg", 27);
    console.info(instance2.colors) //red, blue, green
    instance2.sayName()  //"Greg"
    instance2.sayAge()   //27
    

    这是javascript实现继承的终极方法,很多流行的前端框架内部继承的实现也是基于这一方法的。

    相关文章

      网友评论

          本文标题:基于javascript的对象继承

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