zoukankan      html  css  js  c++  java
  • JavaScript之对象继承

    原型链继承

    function SuperType(){
        this.property = true;
    }
    
    SuperType.prototype.getSuperValue = function(){
        return this.property;
    };
    
    function SubType(){
        this.subproperty = false;
    }
    
    // 继承了 SuperType
    SubType.prototype = new SuperType();
    
    var subType = new SubType();
    console.log(subType.getSuperValue());   // 继承了 SuperType 的 getSuperValue 方法,打印 true
    

    缺点

    1. 如果 SuperType 存在一个引用类型的属性,而 SubType 的原型对象变为 SuperType 的一个实例,这样每个 SubType 的实例都会共用这个引用类型的属性,不同的 SubType 实例对该属性的操作都将会在其它 SubType 实例中体现出来,这跟每个实例拥有自己的属性是违背的。
    function SuperType(){
        this.colors = ["red", "blue", "green"];
    }
    
    function SubType(){            
    }
    
    // 继承了 SuperType
    SubType.prototype = new SuperType();
    
    var subType1 = new SubType();
    subType1.colors.push("black"); // subType1 修改 colors
    console.log(subType1.colors);    // "red,blue,green,black"
    
    var subType2 = new SubType();
    console.log(subType2.colors);    // "red,blue,green,black",subType2 的 colors 值为 subType1 修改之后的值
    
    1. 在创建子类型(SubType)的实例时,不能向超类型(SuperType)的构造函数中传递参数。实际上,应该说是没有办法在不影响所有对象实例(原因如缺点1)的情况下,给超类型的构造函数传递参数。

    借用构造函数继承

    function SuperType(){
        this.colors = ["red", "blue", "green"];
    }
    
    function SubType(){  
        // 继承了 SuperType
        SuperType.call(this); // 通过 apply() 或 call() 执行 SuperType 的构造函数
    }
    
    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"
    

    该方法解决了 原型链继承 的引用型属性共享的问题。

    还有可以在子类型构造函数中向超类型构造函数传递参数,如下例子:

    function SuperType(name){
        this.name = name;
    }
    
    function SubType(){  
        // 继承 SuperType,并传递参数
        SuperType.call(this, "Nicholas");
        
        // 实例属性
        this.age = 29;
    }
    
    var subType = new SubType();
    console.log(subType.name);   //"Nicholas";
    console.log(subType.age);    //29
    

    缺点

    1. 方法都在构造函数中定义,因此函数复用就无从谈起了。而且,在超类型的原型中定义的方法,对子类型而言也是不可见的,结果所有类型都只能使用构造函数模式。

    原型链/构造函数组合继承

    function SuperType(name){
        this.name = name;
        this.colors = ["red", "blue", "green"];
    }
    
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    };
    
    function SubType(name, age){
        // 执行 SuperType 的构造函数,继承 SuperType 的属性
        SuperType.call(this, name);
        
        this.age = age;
    }
    
    // 将 SuperType 的实例赋给 SubType 的原型对象,这样 SubType 可继承 SuperType 原型中的方法
    SubType.prototype = new SuperType();
    
    SubType.prototype.sayAge = function(){
        console.log(this.age);
    };
    
    var  subType1 = new SubType("Nicholas", 29);
    subType1.colors.push("black");
    console.log(subType1.colors);  // "red,blue,green,black"
    subType1.sayName();      // "Nicholas";
    subType1.sayAge();       // 29
    
    
    var subType2 = new SubType("Greg", 27);
    console.log(subType2.colors);  // "red,blue,green"
    subType2.sayName();      // "Greg";
    subType2.sayAge();       // 27
    

    缺点

    1. 无论什么情况,都会调用两次超类型构造函数,一次是在创建子类型原型的时候,一次是在执行子类型构造函数的时候。这样一个 SubType 实例会包含两组 SuperType 的属性,一组在 SubType 实例上,一组在 SubType 原型中。

    原型式继承

    该方法基于已有的对象创建新对象,同时还不必因此创建自定义类型。

    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = Object.create(person); // 使用 person 作为新对象(anotherPerson)的原型
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    
    var yetAnotherPerson = Object.create(person);
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    
    console.log(person.friends);   // "Shelby,Court,Van,Rob,Barbie"
    

    寄生式继承

    该方法创建一个仅用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后再像真地是它做了所有工作一样返回对象。

    function creatAnother(original) {
        var clone = Object.create(original); // 创建一个新对象
        clone.sayHi = function() { // 以某种方式来增强这个对象
            console.log("hi");
        }
        return clone; // 返回该对象
    }
    
    // 使用示例
    var person = {
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = creatAnother(person);
    anotherPerson.sayHi(); // "hi"
    

    寄生/原型链/构造函数组合继承

    该方法解决原型链/构造函数组合继承调用两次超类型构造函数的问题。

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

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    
    function inheritPrototype(subType, superType){
        var prototype = object(superType.prototype);   // 根据超类型原型创建新对象
        prototype.constructor = subType;               // 将新对象的 constructor 设置为子类型
        subType.prototype = prototype;                 // 将新对象赋给子类型的原型
    }
                            
    function SuperType(name){
        this.name = name;
        this.colors = ["red", "blue", "green"];
    }
    
    SuperType.prototype.sayName = function(){
        console.log(this.name);
    };
    
    function SubType(name, age){  
        SuperType.call(this, name);
        
        this.age = age;
    }
    
    inheritPrototype(SubType, SuperType);
    
    SubType.prototype.sayAge = function(){
        console.log(this.age);
    };
    
    var subType1 = new SubType("Nicholas", 29);
    subType1.colors.push("black");
    console.log(subType1.colors);  // "red,blue,green,black"
    subType1.sayName();      // "Nicholas";
    subType1.sayAge();       // 29
    
    
    var subType2 = new SubType("Greg", 27);
    alert(subType2.colors);  // "red,blue,green"
    subType2.sayName();      // "Greg";
    subType2.sayAge();       // 27
    

    参考资料:《JavaScript高级程序设计(第3版)》第6.3节 继承

  • 相关阅读:
    使用FreeTextBox等控件带来的问题
    DoNet分页控件
    享元模式学习后总结!(见到别人的总结,解我心中迷惑,认可)
    基于工作流平台的ITSM系统
    .net工作流在移动公司的部署
    转载:When Office 2003 couldn’t find file SKU011.CAB Office 2003 reinstallation error
    联通公司代理商佣金管理
    知识管理系统分析之一:网络蜘蛛的分析
    自我介绍像猪一样生活
    知识管理的整体架构
  • 原文地址:https://www.cnblogs.com/laixiangran/p/9017161.html
Copyright © 2011-2022 走看看