深入JavaScript对象
ECMA-262把对象定义为:“无序属性的集合,其属性可以包含基本值、对象或者函数“。我们可以把ECMAScript的对象想象成散列表:一组名值对,其中值可以使数据或函数。每个函数都有一个prototype属性,这个属性是一个对象,prototype对象的属性和方法被类型的所有实例共享。Prototype就是通过调用构造函数而创建的那个对象的原型对象。对象通过一个内部属性_proto_绑定到它的原型,这个属性在Firefox,Safari和Chrome浏览器中对开发者可见。所有函数对象的protoType默认指向object对象的原型。如:
<script language="javascript" type="text/javascript">
function Person(name, address) {
this.name = name;
this.address = address;
}
Person.prototype.say = function () {
alert(this.name);
}
var person1 = new Person("Feng", "Henan");
var person2 = new Person("Lee", "Beijing");
alert(person1 instanceof Person);//true
alert(person1 instanceof Object); //true alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true
</script>
构造器Person用来创建新实例。实例person1的原型(_proto_)指向Person.prototype。Person.prototype的原型指向Object.prototype。上面的代码创建的原型链如下
用下面这个例子来展示原型动态特性的魅力的,以免在程序中整出很神奇的BUG。需要用Firefox调试一把。
<script language="javascript" type="text/javascript">
function Person() {
}
var person1 = new Person();
Person.prototype.sayOld = function () {
alert("old test");
};
// Person.prototype = {
// name: "Feng",
// address: "Henan",
// say: function () {
// alert(this.name);
// }
// };
//person1.say();错误不能调用
person1.sayOld();
alert(person1.__proto__.constructor);
var person2 = new Person();
alert(person2.__proto__.constructor);
alert(Person.prototype.constructor);
</script>
注意person1是在添加sayOld方法之前创建的实例,此时调用sayOld()方法正常,firebug调试信息如下:
现在把person1.sayOld()注释掉,把注释掉的代码恢复正常,
但是person1.say()方法不能调用,因为我们重写了原型,person1指向的还是原来的原型,原来的原型不包括say方法。原型图如下: