关于JS原型对象
2017-07-30 本文已影响28人
7天苹果
原型对象的基本概念
无论什么时候,只要创建了一个新函数,就会根据一组特定的规则为该函数创建一个prototype属性,这个属性指向函数的原型对象。
在默认情况下,所有原型对象都会自动获得一个constructor属性,这个属性是一个指向prototype属性所在函数的指针。
每个对象上都支持一个属性_ proto _,这个属性连接存在于实例与构造函数的原型对象之间,而不是存在于实例与构造函数之间。
如下图:

实例person1和person2的内部属性指向了Person.prototype,它们与构造函数没有直接的关系。
使用hasOwnProperty()方法可以检测一个属性是存在于实例中,还是存在于原型中:访问的是实例属性就返回true,原型属性返回false。
比如:
function Person(){
}
Person.prototype.name = "john";
Person.prototype.age = 29;
Person.prototype.job = "software engineer";
Person.prototype.sayName = function(){
alert(this.name);
};
var person1 = new Person();
alert(person1.hasOwnProperty("name")); //false
person1.name = "greg";
alert(person1.name);
person1.hasOwnProperty("name"); //true
获得属性的方法
- Object.keys()
取得的是可枚举的实例属性,接收一个对象为参数,返回一个包含所有可枚举属性的字符串。(不包含原型对象上的属性) - Object.getOwnPropertyNames()
得到所有的实例属性,无论它是否可枚举。
更简单的原型语法
使用一个包含所有属性和方法的对象字面量来重写整个原型对象,可以减少不必要的输入。
function Person(){
}
Person.prototype = {
name : "John";
age:29;
job:"software engineer";
sayName:function(){
alert(this.name);
}
}
这种方法有一个例外:constructor属性不再指向Person了。指向Object构造函数。

所以这种情况下这样做会报错:
function Person(){
}
var friend = new Person();
Person.prototype = {
name : "John";
age:29;
job:"software engineer";
sayName:function(){
alert(this.name);
}
}
friend.sayName(); //error
解决方案是这样:
function Person(){
}
Person.prototype = {
constructor:Person, //添加constructor属性,设置为Person
name : "John",
age:29,
job:"software engineer",
sayName:function(){
alert(this.name);
}
}
var friend = new Person();
friend.sayName(); //John
原型对象的问题
- 省略了构造函数传递初始化参数这一环节,结果所有的实例在默认情况下都将取得相同的属性值。
- 原型模式的最大问题是由其共享的本质所导致的。
原型中所有属性是被许多实例共享的,所以对于包含引用类型值的属性来说,问题就比较突出了。
function 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"
这也是我们为什么不去单独使用原型模式的原因。