美文网首页
JS创建对象方法之工厂方法,构造函数方法

JS创建对象方法之工厂方法,构造函数方法

作者: shandamengcheng | 来源:发表于2019-07-25 15:51 被阅读0次

    JS创建对象方法之工厂方法,构造函数方法

    我们在ECMAScript中创建对象虽然可以通过Object()构造方法或者是对象字面量的方式,但是这两种方式有缺点的:使用同一接口创建很多对象,会产生大量重复的代码。

    JS创建对象之工厂模式

    关于工厂模式,首先简单地从字面意思来理解,为什么叫工厂模式,而不叫其他的名字,我觉得可以这样理解。比如说这个工厂是一个加工手刹的工厂,我们是雇主,我们想要一定数目的手刹,我们只需要把订单交给工厂就可以了,不需要知道这个手刹是怎么制作的,同样工厂会给我们的是已经做好的手刹。我们只需要知道如果我们需要手刹,直接交给工厂解决就可以了。
    那么,ECMAScript中创建对象的工厂模式就是这个意思,即抽象创建具体对象的过程。 由于在ECMAScript中无法创建类,因此我们可以通过函数来封装以特定接口创建对象的细节。

    function createPersonalInfor(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 = createPersonalInfor("Jona",20,"student");
    var person2 = createPersonalInfor("Jone",19,"software engineer");
    

    从上面的代码可以看到,我们通过createPersonalInfor()函数,创建了两个对象,这样无疑节省了不少的代码量。但是这种方法也是有着缺点:没有解决对象识别问题(即怎样知道一个对象的类型)。
    由于我们在createPersonalInfor()中的对象都是通过Object()构造函数创建的,因此不管你的信息是属于哪个对象的,当判断对象的类型时,结果都是Object。比如说我们想要对象A是Company1类型,对象B是Company2类型的,但是如果使用上面的工厂模式,我们就无法判断A和B分别是哪一个类型的。 对于此问题,出现了一个新的模式:构造函数模式

    JS创建对象之构造函数模式

    ECMAScript中的构造函数可以用来创建对象。类似于Object, Array这样的原生构造函数,在运行时会自动出现在执行环境中。即他们是已经存在的函数,不需要我们再去显示的写出这个构造函数,直接用就行了。 我们也可以使用自定义的构造函数,从而自定义对象类型的属性和方法。

    function Person(name,age,job)
    {
        this.name = name;
        this.age = age;
        this.job = job;
        this.sayName = function ()
        {
            alert(this.name);
        }
    }
    var person1 = new Person("Jona",20,"student");
    var person2 = new Person("Jone",19,"software engineer");
    

    从这个例子中,我们可以看到与工厂模式时的不同:

    • 没有显示创建对象
    • 直接将属性和方法赋给this对象
    • 没有return 语句

    在这里注意一种写法,我们这里自定义的构造函数的函数名首字母大写,非构造函数首字母小写,这样主要是为了区别来构造函数和非构造函数。毕竟,构造函数也还是函数。

    我们在创建自定义对象时,使用了new操作符。那么在构造函数调用时,会经历以下几个步骤:

    • 创建一个新对象
    • 将构造函数的作用域赋给新对象(this就指向了该新对象)
    • 执行构造函数中的代码
    • 返回新对象

    我们可以通过person1.constructor 来得知该对象的类型,但是如果已知有哪几种类型,也可以通过instanceof来判断对象类型。

    1.将构造函数当作函数

    构造函数与其他函数的唯一不同就是调用方式不同。但构造函数也还是函数,没有定义构造函数的特殊语法。任何函数,只要通过new操作符来点用,就可以作为构造函数。而任何函数,没有通过new操作符调用,那么就是普通函数。

    var person = new Person("jona",20,"student");
    person.sayName();    //Jona
    
    Person("Jone",19,"nurse");  //添加到了window中,当成了普通函数调用
    window.sayName();    //Jone
    
    //在别的对象中调用
    var o = new Object();
    Person.call(o,"Ravi",30,"teacher");
    o.sayName();      //Ravi
    
    

    2. 构造函数的问题

    那么,构造方法模式有没有缺点呢? 答案是肯定的。

    不知道有没有发现,正如上面我们自定的构造函数,如果构造函数里有方法,那么我们每次创建一个新对象的时候,都会创建一个新的Function()实例,即创建了一个新的对象。“函数是对象,函数名是指针”。虽然每次创建的函数会导致不同的作用域链和标识符解析,但是他们的作用机理都是一样的,比如上面定义的Person()中,都是要显示当前对象的name属性。因此,我们可以把函数定义移到构造函数之外来解决这个问题。

    function Person(name,age,job)
    {
        this.name  = name;
        this.age  = age;
        this.job = job;
        this.sayName = sayName;
    }
    function sayName()
    {
        alert(this.name);
    }
    var person1  = new Person("Jona",20,"student");
    var person2 = new Person("Jone",19,"nurse");
    

    在此例中,由于构造函数中的sayName属性的值等于全局作用域中的sayName函数,这样一来,person1 和 person2 就共享了同一个sayName()函数。

    缺点是什么呢?

    在全局作用域中定义的函数实际上只能被某一个函数调用,这让全局作用域有点名不副实。(这句话可能一时想不明白,请参见博文,我觉得讲的很清楚:
    https://blog.csdn.net/chengdabelief/article/details/50990938 )。
    而且,如果对象需要定义很多方法,那么我们就要在全局作用域中定义很多全局函数,这破坏了自定义引用类型的封装性。
    那么,对于这种问题,可以通过原型模式来解决。

    相关文章

      网友评论

          本文标题:JS创建对象方法之工厂方法,构造函数方法

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