原型模式--5.2

我们创建的每个函数都有一个prototype(原型)属性,这个属性是一个指针,指向通过构造函数而创建的那个对象实例的原型对象。所有对象共享它所包含的属性和方法。

使用原型对象的好处:让所有对象实例共享它所包含的属性和方法。也就是说,不必再构造函数中定义对象实例的信息,而是可以将这些信息直接添加到原型对象中。

但是与构造函数不同的是:新对象的属性和方法是由所有实例共享的。

1、理解函数对象


无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype的属性。

虽然在所有现实中都无法访问到[[prototype]]属性但是可以通过isPrototype()方法来确定对象之间是否存在这种关系。


当然es5中还增加了一个新方法,Object.getPrototypeOf();


每当代码都去某个对象的某个属性的时候,都会执行一次搜索,目标是具有给定名字的属性。如果没有在实例中找到,那么搜索指针将会指向原型对象。

虽然可以通过对象实例访问保存在原型中的值,却不能通过对象实例重写原型中的值。如果我们在实例中添加了一个属性,而该属性与实例原型中的一个属性同名,那么我们创建的该属性会屏蔽原型中的那个属性。即使将这个属性设置为null,也不会回复其指向原型的连接。不过,使用delete操作符可以完全删除实例属性。

使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中。这个方法(不要忘了他是从Object继承来的)只在给定属性存在于实例对象中才会返回true。

in操作符会在通过对象能够访问给定属性时返回true,无论该属性存在于实例中还是原型中。

for-in循环,返回的时所有能够通过对象访问可枚举的属性,其中包括了存在于实例中的属性,也包括存在于原型中的属性,还有屏蔽了原型中不可枚举属性的实例属性。


怎么判断属性是否可枚举---https://segmentfault.com/a/1190000010731448

js中基本包装类型的原型属性是不可枚举的,如ObjectArrayNumber

Object对象的propertyIsEnumerable()方法可以判断此对象是否包含某个属性,并且这个属性是否可枚举。

需要注意的是:如果判断的属性存在于Object对象的原型内,不管它是否可枚举都会返回false

要获取对象上所有的可枚举属性可以Object.keys()方法,这个方法接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。如果你想要得到所有实例属性,无论它是否可枚举,都可以使用Object.getOwnPropertyNames()方法。


更简单的原型语法:

为了减少不必要的输入,也为了视觉上更好地封装原型的功能,更常见的做法是用一个包含所有属性和方法的字面量来重写整个原型对象。(其他最终结果均相同,但是有一个例外:constructor属性已经不再指向Person了。)因为重写了默认的prototype对象 注:js中基本包装类型的原型属性是不可枚举的,如Object, Array, Number等

解决方案:P155

圆形的动态性:

由于在原型中查找值得过程是一次搜索,因此我们对原型对象所做的任何修改都能立即从实例上反应出来---即使是先创建了实例后修改原型也照样如此。(原因可以归结于实例与原型之间得松散连接关系)

但是!!如果不是仅仅增加删除,而是字面量重写了整个原型对象,那么重写原型对象切断了现有原型与任何之前一斤存在的对象实例之间的联系,他们引用的仍然是最初的原型!


原生对象得原型:

可以利用上述原理修改原生对象!但是最好不要这样做,容易引起命名冲突,或者会意外得重写原生方法。


原型对象的问题:

缺点:节省了为构造函数传递参数初始化这一环节,结果所有得实例在默认情况下都将渠道相同的属性值。;;最大的问题是共享本性所导致,对于包含基本指得属性,可以通过添加同名属性来覆盖。但是对于那些引用属性,例如所有实例共享同一个数组emmm一点也不好!!

猜你喜欢

转载自blog.csdn.net/m_oman/article/details/80161099