理解原型对象
- prototype
只要创建一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。 - 原型对象
原型对象包含可以由(自定义的引用类型对象的所有实例对象)共享的属性和方法。 - constructor
在默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性是一个指向prototype属性所在函数的指针。 - [[prototype]]
- 当调用构造函数创建一个新实例后,该实例的内部将包含一个指针(内部属性),指向构造函数的原型对象。
- [[prototype]]存在于实例和构造函数的原型对象之间。
isPrototypeOf()
如果调用isPrototypeOf()方法的对象就是[[prototype]]指向的对象,这个方法就返回true。Object.getPrototypeOf()
返回[[prototype]]的值。当为对象实例添加一个属性时,这个属性就会屏蔽原型对象中保存的同名属性。
hasOwnProperty()
如果属性存在于实例中,返回true
原型与in操作符
- 单独使用
无论属性存在于实例中还是原型中,in操作符通过对象能够访问到该属性,返回true。 - for-in循环中使用
返回所有- 能通过对象访问的
- 可枚举的(enumberated)属性,其中既包括存在于实例中的属性,也包括存在于原型中的属性。
- 屏蔽了原型中不可枚举属性的实例属性,因为所有开发人员定义的属性都是可枚举的。
- Object.keys()
接收一个对象作为参数,返回一个包含所有可枚举属性的字符串数组。 - Object.getOwnPropertyNames()
返回所有实例属性。
更简单的原型语法
为减少不必要的输入,也为了从视觉上更好的封装原型的功能,用一个包含所有属性和方法的对象字面量来重写整个原型对象。
- 弊端
将导致constructor不再指向构造函数,而是指向了Object
使用Object.defineProperty()重设构造函数,只适用于ECMAScript 5兼容的浏览器。
原型的动态性
对原型对象所做的任何修改都能够立即从实例上反映出来,即时先创建了实例后修改原型也如此。
- 原因:
实例与原型之间的松散连接关系。实例和原型对象之间的连接是指针,而非副本,通过指针在原型中搜索。 - 缺陷:
重写整个原型对象,相当于给构造函数的的prototype指针指向了另一个原型对象。
原生对象的原型
除了自定义类型之外,原生的引用类型(Object、Array、String,等等)都在其构造函数的原型上定义了方法。
不建议在产品化的程序中修改原生对象的原型。可能重写。
原型对象的问题
- 省略了为构造函数传递初始化参数,结果所有实例在默认情况下都将取得相同的属性值。
- 对于包含引用类型值的属性,在一个实例中添加同名属性,无法屏蔽原型中的属性值,而是直接修改了。