javascript 无法修改 数组中对象_一文秒懂JavaScript中对象的7种创建方式

1.工厂模式

javascript 代码

f0d501415c47f70e43a54f0c5ec6f0c9.png

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

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

2.构造函数模式

javascript 代码

1464c038bb04e812e8831b9ea7131b11.png

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

没有显示的创建对象

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

没有return语句

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

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

1.创建一个新的对象2.将构造函数的作用域赋给新对象(即this指向这个新对象)3.执行构造函数中的代码4.返回这个新对象

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

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

0a2065fce1ddcdeab55cd7bf05ad5b46.png

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

3.原型模式

javascript 代码

cc9180af49c3dd86f28fe3364b7294fe.png

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

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

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

9cdfcaefd38a109ec8c3c7057cc5e9c5.png

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

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

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

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

15a94764718ab55997f07379f032a244.png

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

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

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

c91cfc13988197de3e726cb5918665cb.png

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

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

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

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

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

javascript 代码

c1ed08684abd2c2c4c498e17656328e8.png
090a55de5d43edf2c292c0f7198cb5b0.png

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

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

javascript代码

edaf8b64481e0a45168ed56ce65bef2c.png

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

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

a83c278302da55617dfffb2ec31b0989.png

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

5.动态原型模式

javascript 代码

7c5dbff0f526836f435bd1a5261ea346.png
fa93c7c1c4b7120fbc04d68c266d2623.png

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

6.寄生构造函数模式

javascript 代码

e818652ed6f2f427641c938361d5acf5.png

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

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

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

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

javascript 代码

b86a09e0dedfd9f5c12cc4afde93df9e.png

结果如下:

a2a1a1f4e017f4fe9ac5ea8e0387ebe7.png

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

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

7.稳妥构造函数模式.

javascript 代码

cd8b2be8f00f4f1ec9d684f667a62407.png

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

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

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

有错误,欢迎大家指出,评论转发哦~

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值