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方法。原型圖如下: