zoukankan      html  css  js  c++  java
  • 创建对象的几种模式

    一般创建对象是用以下两种方式

    new object创建对象:

    var Person = new Object();
    Person.name = "张三";
    Person.age = "18";
    Person.job = "123";

    或者,对象字面量的方式:

    var Person = {
        name:"lisi",
        age:"18",
        job:"123"
    }

    这两种方式的缺点是:同一个接口创建很多对象,会产生大量的重复代码,如var Person1={},var Person2={},为了解决这个问题,人们开始使用工厂模式的一种变体来创建对象。

    一、工厂模式

    由于在ECMAScript中无法创建类,开发人员就发明了一种函数,用函数来封装以特定接口创建对象的细节,如下图:

    function creatPerson(name,age,job){
        var a = new Object();
        a.name = name;
        a.age = age;
        a.job = job;
        return a;
    }
    var person2 = creatPerson("lisi","17","456");

    使用工厂模式创建对象,无论创建多少个对象,都只需要调用creatPerson()函数,并传入相关参数即可。但是工厂模式也留下了一个问题,就是无法区分创建对象类型是什么,在ECMAScript 中的构造函数可用来创建特定类型的对象 。

    二、构造函数模式

    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function(){
            alert(this.name);
        }
    }
    var person1 = new Person("lisi","18","123");

    创建自定义的构造函数,从而定义自定义对象类型的属性和方法 。构造函数也是函数,它与普通函数唯一的区别就是调用方式不同。任何函数,只要用new操作符来调用,那它就可以作为构造函数。
    缺点:函数即对象,sayName 是匿名函数对象;每调用实例化一次构造函数就会创建一个匿名函数对象,不同实例上的同名函数是不相等的,占用内存。

    三、原型模式

    理解原型:只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个 prototype属性,这个属性指向函数的原型对象。
    在默认情况下,所有原型对象都会自动获得一个 constructor(构造函数)属性,这个属性包含一个指向 prototype 属性所在函数的指针。

    function Person(){
    
    }
    Person.prototype = {
        constructor:Person,
        name:"张三",
        age:"18",
        job:"123",
        friends: ['小明', '小刚'],
        sayName:function(){
            alert(this.name);
        }
    }
    var person1 = new Person();

    这里将 Person.prototype 设置为以对象字面量的形式创建的新对象,由于每创建一个新对象,就会同时创建它的 prototype原型对象,
    这个对象也会自动获得 constructor 属性,这个constructor指向这个新创建的object对象,而不是Person对象,为了使其指向Person,
    需添加 constructor:Person

    原型模式的缺点:

    var p1 = new Person();
    var p2 = new Person();
    p2.name = '李四';
    p1.friends.push('小红');// 指向同一个friends数组,修改的是原型中的friends
    console.log(p1.friends);//["小明", "小刚", "小红"]
    console.log(p2.friends);//["小明", "小刚", "小红"]
    console.log(p1.friends == p2.friends);//true

    缺点1:省略了为构造函数传递初始化参数这一环节,结果所有实例在默认情况下都将取得相同的属性值

    缺点2:对于原生构造函数(Object、Array等)的缺点:

    p1的friends和p2的friends相同,因为p1修改了原型对象的friends,但我们需要的是它们不应该相同,
    解决办法:将需要共享的属性或方法在原型中定义,将不需要共享的如:friends,在构造函数中定义

    四、组合使用构造函数和原型模式

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

    function Person(name,age,job){
        this.name = name;
        this.age = age;
        this.job = job;
        this.friends: = ['小明', '小刚'],
    }
    Person.prototype = {
        constructor:Person,
        sayName:function(){
            alert(this.name);
        }
    }

     

  • 相关阅读:
    Java主流日志工具库
    JSON 与 String、Map、JavaBean互转
    Session超时处理
    spring cron表达式(定时器)
    Windows服务器下用IIS Rewrite组件为IIS设置伪静态方法
    JAVA导出Excel(支持多sheet)
    自己实现一个简单的线程池
    数据库
    计算机网络
    HashMap源码分析
  • 原文地址:https://www.cnblogs.com/wangxiaoling/p/9897935.html
Copyright © 2011-2022 走看看