zoukankan      html  css  js  c++  java
  • Javascript面向对象之继承

    与类的创建篇一样,这里先贴出最终代码,再做详细分析:

    // 创建一个父类
    function SuperType(){
        this.company = 'alibaba';
    }

    function SubType(){ SuperType.call(this); // 【1. 调用父类的构造函数】 this.name = 'yunos'; } SubType.prototype = Object.create(SuperType.prototype,{constructor:{value:SubType}}); // 【2. 把父类的原型赋给子类】 var instance = new SubType(); console.log(instance); /*----------------牢记两部关键性的操作,到此为止,已实现理想化的继承------------------------*/ var instance = new SubType(); instance instanceof SubType // true. instance instanceof SuperType // true.

     鉴于部分浏览器尚不支持Object.create, 修正后如下:

    // 辅助函数,解决浏览器不支持Object.create的问题,同时正确指向构造函数
        function createObject(proto, constructor) {
            var newProto;
            if (Object.create) {
                newProto = Object.create(proto);
            } else {
                function Empty(){};
                Empty.prototype = proto;
                newProto = new Empty();
            }
            newProto.constructor = constructor;
            return newProto;
        }
    
    // 创建一个父类
    function SuperType(){
        this.company = 'alibaba';
    }function SubType(){
        SuperType.call(this); // 调用父类的构造函数.
        this.name = 'yunos'; 
    }
    SubType.prototype = createObject(SuperType.prototype, SubType);    // 把父类的原型赋给子类
    
    var instance = new SubType();
    instance instanceof SubType //   true.
    instance instanceof SuperType // true.

    Javascript中最常用的继承模式: 原型链 + 借用构造函数 = 组合继承(又称伪经典继承)。

    原型链继承:

    function SuperType(){
        this.company = 'alibaba';
    }
    SuperType.prototype.getSuperValue = function(){
        return this.company;
    }
    
    function SubType(){
        this.name = 'yunos';
    }
    SubType.prototype = new SuperType();
    
    var instance = new SubType();
    console.log(instance);

    众所周知,Javascript是通过prototype来实现继承的,在此我们创建父类的实例重写了 SubType.prototype。
    换句话说,原来存在于 SuperType 的实例中的所有属性和方法现在也存在于 SubType.prototype中了。
    如下所示:

    当然,不要忘记最后一环,所有的引用类型默认都继承了Object,这一环也是通过原型链来实现的,所有函数默认的原型 { constructor : '...' }都是Object的实例。

    尽管原型链如此强大,可以用它来实现继承,但在实践中我们很少这样做,因为它存在一个严重的问题:父类的属性会成为子类的原型属性,

    而当原型属性包含引用类型值时,该原型属性会被类的所有实例共享,在一个实例上进行的修改,会影响到其他实例。

    借用构造函数继承:

    在解决原型中包含引用类型值多带来问题的过程中,使用一种叫做借用构造函数的技术(有时候也叫做伪造对象或经典继承)。 这种技术思想相当简单,即在子类型构造函数的内部调用父类的构造函数。  —— 函数只不过是在特定环境中执行代码的对象,因此通过使用apply 和 call 方法可以在新创建的对象上执行构造函数,如下所示:

    function SuperType(){
        this.colors = ["red", "blue", "green"];
    }
    
    function SubType(){
        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"

    通过借调,我们实际上是在(未来将要)新创建的SubType 实例的环境下调用了 SuperType 构造函数。 这样,就会在新SubType对象上执行 SuperType() 函数中定义的所有对象初始化代码。 然后, SubType的每个实例就都会具有自己的 colors 属性的副本了。

    而且它还具有一个很大的优势,即可以在子类构造函数中向父类的构造函数传递参数:

    function SuperType(name){
        this.name = name;
    }
    
    function SubType(){
      SuperType.call(this, "yunos");
      this.age = 29;
    }
    
    var instance = new SubType();
    console.log(instance.name);    // "yunos";
    console.log(instance.age);      // 29

    为了确保父类构造函数不会重写子类型的属性,可以在调用父类构造函数后,再添加应该在子类型中定义的属性。

    组合继承:

    将原型链和借用构造函数的技术组合到一块,从而发挥二者之长,是当前应用最广泛的继承方法:

    function SuperType(){
        this.company = "alibaba";
    }
    SuperType.prototype.getSuperValue = function(){
        return this.company;
    }
    
    function SubType(){
      SuperType.call(this);   // 【借调父类的构造函数】
      this.name = "yunos";
    }
    SubType.prototype = new SuperType();
    
    var instance1 = new SubType();
    console.log(instance1);

     

    虽然并不完美,但类的功能终于具备了,无明显弊端,使用方法也比较简单,所以被广泛使用。

    至此本文应该结束了,但严谨的,偏执的,追求完美的程序员,一直在探求更为完美的实现方式,于是便有了下边的内容:

    Javascript中最理想的继承范式: 原型式 —> 寄生式 —> 寄生组合式继承(广泛应用于YUI、KISSY中)—> 最终继承

    // 辅助方法,用以正确继承父类原型
    function inheritPrototype(subType, superType){
        function F(){};
        F.prototype = superType.prototype;
        var protoObj = new F();
    
    }
  • 相关阅读:
    飞入飞出效果
    【JSOI 2008】星球大战 Starwar
    POJ 1094 Sorting It All Out
    POJ 2728 Desert King
    【ZJOI 2008】树的统计 Count
    【SCOI 2009】生日快乐
    POJ 3580 SuperMemo
    POJ 1639 Picnic Planning
    POJ 2976 Dropping Tests
    SPOJ QTREE
  • 原文地址:https://www.cnblogs.com/v10258/p/3293179.html
Copyright © 2011-2022 走看看