原型对象的基本概念
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。
在默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性是一个指向prototype属性所在函数的指针。
每个对象上都支持一个属性 proto ,这个属性连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。
如下图:
实例person1和person2的内部属性指向了Person.prototype,它们与构造函数没有直接的关系。
使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中:访问的是实例属性就返回true,原型属性返回false。
比如:
获得属性的方法
- Object.keys()
取得的是可枚举的实例属性,接收一个对象为参数,返回一个包含所有可枚举属性的字符串。(不包含原型对象上的属性) - Object.getOwnPropertyNames()
得到所有的实例属性,无论它是否可枚举。
更简单的原型语法
使用一个包含所有属性和方法的对象字面量来重写整个原型对象,可以减少不必要的输入。
这种方法有一个例外:constructor属性不再指向Person了。指向Object构造函数。
所以这种情况下这样做会报错:
解决方案是这样:
原型对象的问题
- 省略了构造函数传递初始化参数这一环节,结果所有的实例在默认情况下都将取得相同的属性值。
- 原型模式的最大问题是由其共享的本质所导致的。
原型中所有属性是被许多实例共享的,所以对于包含引用类型值的属性来说,问题就比较突出了。12345678910111213141516171819function Person(){}Person.prototype = {name : "John";age:29;friends:["shelby","jenny"]job:"software engineer";sayName:function(){alert(this.name);}}var person1 = new Person();var person2 = new Person();person1.friends.push("van");alert(person1.friends); //"shelby","jenny","van"alert(person2.friends); //"shelby","jenny","van"
这也是我们为什么不去单独使用原型模式的原因。