理解原型對象
只要創建了一個函數,函數自動獲得一個prototype屬性,這個屬性指向函數的原型對象。
在默認情況下,所有原型對象都會自動獲得一個constructor
屬性,這個屬性指向prototype屬性所在的構造函數
除了 constructor 屬性,還有從Object繼承來的屬性,通過這個構造函數,我們還可繼續爲原型對象 添加其他屬性和方法
//構造函數
function Person(){
}
//原型對象
Person.prototype
//原型對象constructor屬性指向Person
Person.prototype.constructor =》Person
//給構造函數原型對象增加屬性和方法
Person.prototype.funName = function(){}
Person.prototype.varName = '123'
當使用構造函數實例化一個對象,這個實例對象包含一個指針(內部屬性),指向構造函數的原型對象。
Firefox
、Safari
和Chrome
在每個對象上都支持一個屬性 __proto__;而在其他實現中,這個屬性對腳本則是完全不可見的
var person = new Person();
person.__proto__ === Person.prototype //true
這個連接存在於實例與構造函數的原型對象之間,而不是存在於實例與構造函數之間
。
原型關係的確認
- isPrototypeOf
Person.prototype.isPrototypeOf(person); //true
- Object.getPrototypeOf() 獲取某個實例對象的原型
Object.getPrototypeOf(person) == Person.prototype //true
屏蔽原型屬性
如果給實例添加屬性與原型對象同名,原型中的屬性會被實例上的屬性屏蔽
function Person(){
}
Person.prototype.name = 'Allen';
Person.prototype.sayName = function(){
alert(this.name)
}
var person = new person();
person.name = 'Bob';
alert(person.sayName());//Bob 來自實例
使用 hasOwnProperty()方法可以檢測一個屬性是存在於實例中,還是存在於原型中。
person.hasOwnProperty("name"); //true
原型與in操作符
- 單獨使用
無論在實例還是在原型中,始終返回true
'name' in person;//true
- for in循環
遍歷實例和原型上可枚舉的屬性
可以通過Object.keys()訪問實例對象的可枚舉屬性
Object.keys(obj) //返回實例對象可枚舉屬性數組
字面量重寫原型對象
function Person(){ }
Person.prototype = {
constructor : Person,//constructor 默認不再指向Person,指向Object,重新定向到person
name : "Nicholas",
age : 29
}
原生對象的原型
所有原生引用類型(Object、Array、String,等等)都在其構造函數的原型上定義了方法。
例如,在 Array.prototype 中可以找到 sort()方法,而在 String.prototype 中可以找到 substring()方法,如下所示。
alert(typeof Array.prototype.sort); //"function"
alert(typeof String.prototype.substring); //"function"
通過原生對象的原型,不僅可以取得所有默認方法的引用,而且也可以定義新方法。可以像修改自 定義對象的原型一樣修改原生對象的原型,因此可以隨時添加方法。下面的代碼就給基本包裝類型 String
添加了一個名爲 startsWith()
的方法。
String.prototype.startsWith = function (text) {
return this.indexOf(text) == 0;
};
var msg = "Hello world!";
alert(msg.startsWith("Hello")); //true