JavaScript中对象的7种创建方式

作者: 前端项目部 | 来源:发表于2019-06-28 13:54 被阅读7次

    1.工厂模式

    javascript 代码

    工厂模式:能根据接受的参数来创建出一个person对象.也可以无数次的调用这个函数,每次都会返回一个包含3个属性和1个方法的对象.

    工厂模式虽然解决了创建多个相似对象的问题,但却没有解决对象识别的问题(即怎样知道一个对象的类型).

    2.构造函数模式

    javascript 代码

    构造函数模式:创建对象要使用new关键字.编码规范要求把构造函数首字母大写以示区分.还有什么和工厂模式不一样的呢?

    没有显示的创建对象

    直接将属性值和方法赋值给了this对象

    没有return语句

    可以通过 instanceof 操作符来检测对象类型

    使用new关键字创建一个对象发生了以下4个步骤

    1.创建一个新的对象

    2.将构造函数的作用域赋给新对象(即this指向这个新对象)

    3.执行构造函数中的代码

    4.返回这个新对象

    通过图片结果可以看到,people1和people2虽然是两个不同的对象,但各自的constructor属性却相同(即具有相同的构造函数).

    构造函数模式的不足:每一个方法都要在实例上重新创建一遍.people1和people2都有一个名为speakName的方法,它们相同吗

    可以看到,结果为false,说明构造函数模式创建的不同实例的同名函数是不一样的.

    3.原型模式

    javascript 代码

    在原型模式中,我把所有的属性和方法全都写在了prototype中.我们创建的每一个函数都有一个prototype属性,prototype属性是一个指针,

    指向一个原型对象,这个对象中包含了所有共享的属性和方法.所以可以看到新建出来的两个实例的方法是完全一样的,因为他们不属于实例函数,而是原型函数.

    如果现在给people1新增加一个speakName方法,结果又会如何呢?

    可以看到,现在结果是false了,因为现在people1的speakName方法覆盖了Prototype上的同名方法.在JS中,代码读取到某个对象的属性时,先在对象实例中查找有没有该属性

    如果找到了,则返回该属性的值,如果没有找到则到Prototype上去查找.这就是为什么实例会共享Prototype上属性和方法的原因.如果想要重新访问Prototype中的属性可以

    使用delete操作符来删除实例中的属性.

    需要注意的一点有:原型链具有动态性,我们对原型对象所做的任何修改都会立即从实例上反映出来.即使是先创建了实例,后修改原型也是如此.如图

    可以看到,我先创建的对象people1和people2,即使后修改原型对象上的方法或增加一个方法,对象上的方法也跟着改变了并且新增加的方法也可以正常的访问到,

    而且两个构造出来的对象的方法都被改变了.

    但要注意的是:如果这里重写整个原型对象,那情况就不一样了.

    可以看到,这里我重写了原型对象,但是却发现people1的speakName方法并没有改变,而且也不能访问到新增加的speakAge方法.报错说not a function.这又是为什么呢?

    还是上面说到的,新创建一个对象时,会自动获得一个constructor属性指向创建该对象的原型对象,而这里把原型对象修改为另一个对象时也就切断了构造函数与最初原型的联系.

    即原先创建的对象引用的依然是最初的原型.

    原型模式的缺点:省略了传递参数,导致所有的实例在默认情况都取得相同的属性值.当然这还不算原型模式最大的缺点,最大的缺点是,所有属性都被全部实例所共享,这对于方法是

    非常合适的,对包含基本值的属性也没多大的影响,只是重写覆盖后会在原型上留下无用的属性.然而,对于包含引用类型值的属性来说,问题就比较突出了.看下面的例子.

    javascript 代码

    可以看到,由于friends存在于People.prototype中,所以通过people1对friends的修改也会反映在别的实例中,这就是不单独使用原型模式的原因.

    4.组合使用构造函数模式和原型模式

    javascript代码

    组合使用构造函数模式和原型模式:创建自定义类型的最常见方式,用构造函数模式来定义实例属性,原型模式来定义共享属性和方法.这样,每一个实例

    都有自己的实例属性的副本,但同时又共享着对方法的引用,最大限度的节省了内存,而且这种混合模式还支持向构造函数传递参数,可谓集两家之长.

    通过结果可以看见,现在people1对friends操作就不会影响别的对象了.

    5.动态原型模式

    javascript 代码

    动态原型模式:它把所有的信息都封装在了构造函数中,仅在某个必要的方法是否存在来决定是否初始化原型.在这个例子中,只有当sayName方法不存在的时候才会将它添加到原型中.这段代码只会在初次调用构造函数才会执行,此后,原型已经初始化,不需要再做什么修改了.

    6.寄生构造函数模式

    javascript 代码

    寄生构造函数模式:基本思想是创建一个函数,该函数的作用仅仅是封装创建对象的代码,然后返回新创建的对象.除了使用了

    new操作符以外,这个模式和第一种工厂模式其实是一模一样的.

    这个模式可以在特殊的情况下为对象创建构造函数.比如我们想创建一个具有额外方法的特殊数组,由于不能直接修改Array

    的构造函数,因此可以使用这个模式.

    javascript 代码

    结果如下:

    关于寄生构造函数,有一点需要注意.返回的对象和构造函数或构造函数的原型属性之间都没有关系,也就是说,不能通过instanceof来

    确定对象的类型.所以在能使用其它模式的情况下尽量不要使用此种模式

    7.稳妥构造函数模式.

    javascript 代码

    稳妥构造函数模式:在以这种模式创建的对象中,除了使用speakName方法外没有其它办法访问name的值.这样创建的对象叫作稳妥对象.

    稳妥模式提供的这种安全性,使得它非常适合在某些安全环境——例如,ADsafe(www.adsafe.org)和Caja(http://code.google.com/p/google-caja/)提供的环境——

    下使用。(与寄生构造函数模式类似,这种模式创建的对象和构造函数之间也没有联系,也不能通过Instanceof来确定对象的类型)

    以上就是我关于js中创建对象的理解.从7月中旬到现在,自己学习H5也快两个月了,学了就忘,还是得找个地方写写东西.加深一下理解.由于本人刚学习前端不久,如果有什么地方

    有错误,欢迎大家指出

    相关文章

      网友评论

        本文标题:JavaScript中对象的7种创建方式

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