理解原型對象
每創建一個函數,就會同時創建它的 Prototype 對象,即原型對象。每個函數都有一個 prototype 屬性,這個屬性指向函數的原型對象。在默認情況下,所有原型對象都會自動獲取一個 constructor(構造函數) 屬性,這個屬性是一個指向 prototype 屬性所在函數的指針。例如:
function Person(){
}
Person.prototype.constructor 指向 Person 。通過這個構造函數,我們還可以爲原型對象添加其他屬性和方法,如下所示:
function Person( ){
}
Person.prototype.name = "Nicholas";
}
var person1=new Person( );
person1.sayName( ); //"Nicholas"
var person2 = new Person( );
person2.sayName( ); //"Nicholas"
雖然無法直接訪問Prototype,但可以通過isPrototypeOf( )方法確定對象之間是否存在這種關係。例如:
alert(Person.prototype.isPrototypeOf(person1)); //true
alert(Person.prototype.isPrototypeOf(person2)); //true
ECMAScript 5中增加了一個新方法 Object.getPrototypeOf() 返回 Prototype 的值。
alert(Object.getPrototypeOf(person1)==Person.prototype); //true
alert(Object.getPrototypeOf(person1).name); //"Nicholas"
雖然可以通過對象實例訪問原型中的值,但卻不能通過對象實例重寫原型中的值。在實例中添加的與原型重名的屬性,將覆蓋原型中的屬性,使用 delete 操作符可以完全刪除實例屬性,從而訪問原型屬性。如下所示:
function Person( ){
}
Person.prototype.name = "Nicholas";
}
var person1 = new Person( );
var person2 = new Person( );
person1.name = "Greg";
alert(person1.name); //"Greg"
alert(person2.name); //"Nicholas"
delete.person1.name;
alert(person1.name); //"Nicholas"
使用 hasOwnProperty( ) 方法(從Object繼承來)可以檢測一個屬性是否存在於實例中。如:
function Person( ){
}
Person.prototype.name = "Nicholas";
}
var person1 = new Person( );
alert(person1.hasOwnProperty("name")); //false
person1.name = "Greg";
alert(person1.name); //"Greg"
alert(person1.hasOwnProperty("name")); //true
delete person1.name;
alert(person1.hasOwnProperty("name")); //false
訪問原型和實例屬性
單獨使用 in 操作符
無論要訪問的屬性存在於實例還是原型中,都會返回 truth .例如:
function Person( ){
}
Person.prototype.name = "Nicholas";
}
var person1 = new Person( );
//同時使用hasOwnProperty()方法和in操作符可以確定該屬性在實例中還是原型中
alert(person1.hasOwnProperty( " name" )); //false
alert("name" in person1); //true
person1.name = "Greg";
alert(person1.hasOwnProperty( " name" )); //true
使用 for-in 循環
返回的是所有能夠通過對象訪問的、可枚舉(enumerated)的屬性,包括實例和原型中的屬性。覆蓋了原型中不可枚舉屬性的實例屬性也會在 for-in 循環中返回。
根據規定,所有開發人員定義的屬性(和函數)都是可枚舉的,只有IE8及更早版本中例外。IE早期版本中的bug使得覆蓋不可數枚舉的實例屬性不會再 for-in 循環中出現 。如:
var o = {
//原型的 toString()方法的Enumerable 值爲false
toString : function {
return "My Object";
}
};
for ( var prop in o) {
if (prop == "toString") { // 在IE中跳過Enumerable 值爲false的方法
alert ( "Found toString !"); //在IE中不會顯示
}
}
ECMAScript 也將 constructor 和 property 屬性的 Enumerable 特性設置爲 false ,但並不是所有瀏覽器都按此實現。
Object.keys( ) 方法
取得對象上所有可枚舉的實例屬性( 不包含原型上的屬性),例如:
function Person( ){
}
Person.prototype.name = "Nicholas";
Person.prototype.age = "29";
Person.prototype.sayName = function ( ){
alert ( this.name );
};
var keys = Object.keys(Person.prototype);
alert(keys); //"name,age,sayName"
var person1=new Person();
Person1.name = "Mary";
var keys = Object.keys(person1);
alert(keys); //"name,age"
Object.getOwnPropertyNames( ) 方法
獲得所有實例屬性,不管是否可枚舉,可使用。如:
var keys = Object.getOwnPropertyNames( Person.prototype);
alert(keys); //"constructor , name, age, sayName"
Object.keys( ) 和 Object.getOwnPropertyNames( ) 方法都可以替代 for-in 循環。支持這兩個方法的瀏覽器有 IE9+、Firefox 4+、Safari 5+、Opera 12+和Chrome。