在javascript中创建对象由很多种方式,如工厂模式、构造函数模式、原型模式等:
<pre name="code" class="html">//工厂模式
function createperson(name,age,job)
{
var o = new object;
o.name = name;
o.age = age;
o.job = job;
o.sayname = function()
{
alert(this.name);
}
return o;
}
var person = createperson('dw',20,'it');
其等价的原型模式:
function person()
{
}
person.prototype =
{
name:dw,
age:20,
job:it,
sayname:function()
{
alert(this.name);
}
};
var person2 = new person;
在javascript中,每个函数都有prototype属性,该属性是一个指向原型对象的指针,可以用于创建所有实例共享的属性的和方法。在原型模式下,在创建一个实例person3
var person3 = new person;
person2.name; //dw
person3.name; //dw
person2和person3的name属性都返回dw。原型对象的属性和方法被所有特定类型的实例共享。在默认的情况下,每个原型对象会自动获得一个constructor属性,用于指向prototype属性所在函数的指针,如person.prototype.constructor指向person
alert(person.prototype.constructor); //返回person的构造函数
//person.prototype.constructor只是指向person的一个指针,与person并不相等
//以下均返回false
alert(person.prototype.constructor === person)
alert(person.prototype.constructor == person)
实例、原型对象、构造函数的三角恋关系如下图所示:
在每一个实例的内部都有一个指针指向原型对象,在ecma-262的第五版称之为[[prototype]]。在原型模式下创建的实例与构造函数没有直接的关系。
虽然无法访问[[prototype]],但可以用isprototypeof()方法来确定对象是否是原型对象。
alert(person.prototype.isprototypeof(person2)); //true
alert(person.prototype.isprototypeof(person3));//true
因为在实例内部均有一个指向person.prototype的指针,所以均返回true。在ecmascript 5中,可以用object.getprototypeof()返回[[prototype]],即返回原型对象
alert(object.getprototypeof(person2) == person.prototype); //true
alert(object.getprototypeof(person2).name); //dw
注意:虽然可以用实例访问原型中的值,但是不能通过实例重写原型中的值,即实例中添加了与原型中同名的属性,则原型的同名属性被屏蔽。
person2.name=qs;
alert(person2.name);//qs
即使将name属性设置为null,仍然不能访问原型中的name。可以用delete删除实例的name属性,则可以重新访问原型中的name.
<pre name="code" class="html">person2.name = null;
alert(person2.name); //null
delete person2.name;alert(person2.name); //dw
对于同名属性,可以用hasownproperty(propertyname)方法检测属性是属于实例还是原型,该方法只有在给定的属性存在实例中时才返回true