• js中的对象创建与继承


    对象创建

    1.工厂模式

    优点:解决了创建多个相似对象的问题
    缺点:没有解决对象识别问题;每一个对象都有一套自己的函数,浪费资源

    function createPerson(name, age, job) {
        var o = new Object();
        o.name = name;
        o.age = age;
        o.job = job;
        o.sayName = function () {
            alert(this.name);
        };
        return o;
    }
    
    //////////////////////////////////////////////////////////////
    var person1 = createPerson("Nicholas", 29, "Software Engineer");
    var person2 = createPerson("Greg", 27, "Doctor");
    
    person1.sayName(); //"Nicholas"
    person2.sayName(); //"Greg"
    

    2.构造函数模式

    优点:可以用来创建特定类型的对象
    缺点:每个方法都要在每个实例上重新创建一遍

    function Person(name, age, job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function(){
            alert(this.name);
        };
    }
    
    
    /////////////////////////////////////////////////////////////
    var person1 = new Person("Nicholas", 29, "Software Engineer");
    var person2 = new Person("Greg", 27, "Doctor");
    

    3.原型模式

    优点:所有对象实例可以共享它所包含的属性和方法
    缺点:共享性,所有的均共享,对龚鸥的固然很好,但不能私有各自属性了

    // 写法1:
    function Person() {}
    Person.prototype = {
        constructor: Person,
        name: "Nicholas",
        age: 29,
        job: "Software Engineer",
        sayName: function() {
            alert(this.name);
        }
    }
    
    
    // 写法2:
    function Person(){}
    Person.prototype.name = "Nicholas";
    Person.prototype.age = 29;
    Person.prototype.job = "Software Engineer";
    Person.prototype.sayName = function(){
        alert(this.name);
    };
    
    //////////////////////////////////////////////
    var person1 = new Person();
    person1.sayName(); //"Nicholas"
    var person2 = new Person();
    person2.sayName(); //"Nicholas"
    alert(person1.sayName == person2.sayName); //true
    

    4.构造函数模式和原型模式

    思路:构造函数模式用于定义实例属性,而原型模式用于定义方法和共享的属性
    优点:每个实例都会有自己的一份实例属性副本,但同时又共享着对方法的引用,最大限度的节省了内存
    缺点

    关于constructor的补充知识点:

    1. 只要创建了一个新函数,就会根据一组特定的规则为这个函数创建一个prototype属性,这个属性指向函数的原型对象。
    2. 在默认情况下,所有原型对象都会自动获得一个constructor构造函数属性,这个属性会包含一个指向protoype属性所在函数的指针。
    function Person(name, age, job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.friends = ["Shelby", "Court"];
    }
    Person.prototype = {
        constructor : Person,
        sayName : function(){
            alert(this.name);
        }
    }
    
    
    /////////////////////////////////////////////////////////
    var person1 = new Person("Nicholas", 29, "Software Engineer");
    var person2 = new Person("Greg", 27, "Doctor");
    person1.friends.push("Van");
    alert(person1.friends); //"Shelby,Count,Van"
    alert(person2.friends); //"Shelby,Count"
    alert(person1.friends === person2.friends); //false
    alert(person1.sayName === person2.sayName); //true
    

    5.动态原型模式

    思路:和4相比只是多了一个函数存在的检测

    function Person(ame,age,job){
         //属性
         this.name = name;
         this.age = age;
         this.job = job;
         //方法
         if (typeof this.sayName != "function"){
              Person.prototype.sayaName = function(){
                  alert(this.name);
              }
         }
    }
    
    
    /////////////////////////////////////////////////////////
    var friend = new Person("Nicholas",29,"Software Engineer");
    friend.sayName();  // Nicholas
    

    6.寄生构造函数模式

    从表面上看是和工厂模式一样,只是最后实例化了一次,而工厂模式是没有再实例化

    function Person(name,age,job){
         var o = new Object();
         o.name = name;
         o.age = age;
         o.job = job;
         o.sayName = function(){
              alert(this.name);
         }
    }
    
    /////////////////////////////////////////////////////////
    var friend = new Person("Nicholas",29,"Software Engineer");
    friend.sayName();  // Nicholas
    

    7.稳妥构造函数模式

    所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象。稳妥构造函数遵循与寄生构造函数类似的模式,有两点不同:
    1.新创建对象的实例方法不引用this
    2.不使用new操作符调用构造函数

    function Person(name,age,job){
         //创建要返回的对象
             var o = new Object();
         // 可以在这里定义私有变量和函数
         //添加方法
         o.sayName = function(){
              alert(name);
         }
         return o;
    }
    
    
    /////////////////////////////////////////////////////////
    var friend = Person("Nicholas",29,"Software Engineer");
    friend.sayName();  // Nicholas
    

    继承

    1.原型链继承

    思路:用父类实例来充当子类实例对象
    缺点
    1.共享(包含引用类型值的原型属性会被所有实例共享)
    2.不能传参(没有办法在不影响对象实例的情况下给超类型的构造函数传递参数)

    function SuperType() {  // 定义父函数
      this.property = true;
    };
    
    SuperType.prototype.getSuperValue = function() {  // 给父函数添加方法
      return this.property;
    };
    
    function SubType() {  // 定义子函数
      this.subproperty = false;
    };
    
    SubType.prototype.getSubValue = function() {  // 给子函数添加方法
      return this.subproperty;
    };
    
    /////////////////////////////////////
    SubType.prototype = new SuperType();  // (关键)
    
    var instance = new SubType();  // 实例化instance
    alert(instance.getSuperValue()); //true
    

    2.借用构造函数

    思路:借父类的构造函数来增强子类实例(等于把父类的实例属性复制了一份给子类实例装上了)
    优点:可传参(可以在子类型的构造函数向超类型的构造函数传递参数)
    缺点:不能复用(超类型原型链中定义的方法对子类是不可见的)

    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"
    

    3.组合继承

    思路:把实例函数放在原型对象上,以实现函数复用
    优点:无共享问题,可传参,可复用
    缺点:父类构造函数会被调用两次,生成两份,而子类实例上的那一份屏蔽了子类原型上的,内存浪费。

    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
    

    4.原型式继承

    思路:用Object函数得到一个空的新对象,再逐步增强填充实例属性
    优点:从已有的对象上衍生新对象,不需要创建自定义类型
    缺点:共享问题

    Object.create() :ES5中规范了原型式继承
    参数1:用作新对象原型的对象
    参数2:为新对象定义额外属性的对象

    function object(o){
        function F(){}
        F.prototype = o;
        return new F();
    }
    
    var person = {  // 父函数
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = object(person);  // (关键)子1继承父
    anotherPerson.name = "Greg";
    anotherPerson.friends.push("Rob");
    
    var yetAnotherPerson = object(person);  // (关键)子2继承父
    yetAnotherPerson.name = "Linda";
    yetAnotherPerson.friends.push("Barbie");
    
    alert(person.friends); //"Shelby,Court,Van,Rob,Barbie"
    

    5.寄生式继承

    思路:创建一个用于封装继承过程的函数,该函数在内部以某种方式来增强对象,最后返回
    优点:不需要创建自定义类型
    缺点:不能复用

    function createAnother(original) {
        var clone = object(original); //通过调用函数创建一个新对象
        clone.sayHi = function(){ //以某种方式来增强这个对象
            alert("hi");
        };
        return clone; //返回这个对象
    }
    
    var person = {  // 父函数
        name: "Nicholas",
        friends: ["Shelby", "Court", "Van"]
    };
    
    var anotherPerson = createAnother(person);  // (关键)子函数继承父函数
    anotherPerson.sayHi(); //"hi"
    

    6.寄生组合式

    思路:切掉了原型对象上多余的那份父类实例属性

    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);
    };
    
  • 相关阅读:
    关于JAVA中的static方法、并发问题以及JAVA运行时内存模型
    【设计模式】抽象工厂模式
    spring mvc4.1.6 + spring4.1.6 + hibernate4.3.11 + mysql5.5.25 开发环境搭建及相关说明
    struts2.3.24 + spring4.1.6 + hibernate4.3.11+ mysql5.5.25开发环境搭建及相关说明
    git中Please enter a commit message to explain why this merge is necessary.
    扒一扒开源世界有哪些licenses?
    string.Format出现异常:输入字符串的格式不正确 Exception during StringFormat
    node-glob学习
    js中对URL进行转码与解码
    程序员如何修炼管理思维
  • 原文地址:https://www.cnblogs.com/Yfling/p/6731807.html
Copyright © 2020-2023  润新知