JavaScript是一門動態語言, 你能夠在任什麼時候候向對象上添加屬性,以下瀏覽器
function Student() { this.name = 'LeBron James'; this.gender = 'Male'; } var studObj1 = new Student(); studObj1.age = 15; alert(studObj1.age); // 15 var studObj2 = new Student(); alert(studObj2.age); // undefined
正如上面的實例, age
屬性附加在 studObj1
實例上. 然而 studObj2
實例沒有這個屬性, 由於 age
屬性只在 studObj1
實例上定義了.函數
那麼, 若是想在後期添加一個屬性且能被全部的實例所共享, 該怎麼辦? 答案這就今天主角 Prototype
.工具
Prototype
是一個對象, 默認狀況下與JavaScript中的任何一個函數或對象有關, 只是惟一區別在於函數的prototype
屬性是可訪問
和可修改
的,而對象
的prototype
屬性是不可見的.this
默認狀況下任何一個函數包含 Prototype
對象, 以下圖:spa
prototype
對象是一種特殊類型的可枚舉對象, 能夠將須要附加屬添加到其上,這些屬性將在其構造函數的全部實例之間共享。prototype
所以, 把上面的示例中使用函數的 prototype
來添加屬性,以便於全部對象中均可以訪問到, 以下:3d
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.age = 15; var studObj1 = new Student(); alert(studObj1.age); // 15 var studObj2 = new Student(); alert(studObj2.age); // 15
使用 字面量
或 經過 new關鍵字和構造函數
的方式建立的每個對象都包含 __proto__
屬性, 該屬性指向建立此對象的函數的 原型對象
.調試
你能夠在谷歌和火狐開發者調試工具中查看該屬性(__proto__
) , 根據下面的示例:code
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } var studObj = new Student(); console.log(Student.prototype); // object console.log(studObj.prototype); // undefined console.log(studObj.__proto__); // object console.log(typeof Student.prototype); // object console.log(typeof studObj.__proto__); // object console.log(Student.prototype === studObj.__proto__ ); // true
正如上面例子看到, 函數經過 [[函數名稱]].prototype
方式訪問到原型對象. 可是, 對象(實例)並無暴露出 prototype
屬性,而是使用 __proto__
來訪問它.對象
前面說起到, 原型對象在對象中是不可見. 使用 Object.getPrototypeOf(obj)
方法來訪問實例的原型對象. (這也是推薦方式, __proto__
並非標準屬性, 在IE11如下其它瀏覽器中沒有實現).
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } var studObj = new Student(); Student.prototype.sayHi= function(){ alert("Hi"); }; var studObj1 = new Student(); var proto = Object.getPrototypeOf(studObj1); // returns Student's prototype object alert(proto.constructor); // returns Student function
Object 原型對象包含以下 屬性
和 方法
屬性 | 描述 |
---|---|
constructor |
返回建立該實例的構造函數 |
__proto__ |
指向建立該實例的構造函數的原型對象. |
方法 | 描述 |
---|---|
hasOwnProperty() |
返回一個布爾值,指示對象是否包含指定的屬性做爲該對象的直接屬性,而不是經過原型鏈繼承。 |
isPrototypeOf() |
返回一個布爾值,指示指定的對象是否位於調用此方法的對象的原型鏈中。 |
propertyIsEnumerable() |
返回一個布爾值,該布爾值指示指定的屬性是否可枚舉。 |
toLocaleString() |
返回本地格式的字符串. |
toString() |
返回對象字符串形式. |
valueOf() |
返回指定對象的原始值. |
Chrome 和 Firfox 將對象的原型表示爲 __proto__
, 而內部引用爲 [[Prototype]]
. IE不支持,只有IE11
包含它.
如上所述, 每一個對象都能連接到函數的原型對象. 若是您更改了函數的原型, 則只有新對象將連接到更改後的原型. 全部其餘現有對象仍然連接到舊的函數原型. 下面實例來演示這個場景:
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.age = 15; var studObj1 = new Student(); alert('studObj1.age = ' + studObj1.age); // 15 var studObj2 = new Student(); alert('studObj2.age = ' + studObj2.age); // 15 Student.prototype = { age : 20 }; var studObj3 = new Student(); alert('studObj3.age = ' + studObj3.age); // 20 alert('studObj1.age = ' + studObj1.age); // 15 alert('studObj2.age = ' + studObj2.age); // 15
原型對象被JavaScript引擎用來作兩件事:
function Student() { this.name = 'LeBron James'; this.gender = 'M'; } Student.prototype.sayHi = function(){ alert("Hi"); }; var studObj = new Student(); studObj.toString();
在上面的示例, toString()
方法在 Student
中沒有定義, 那麼它是如何以及從哪裏找到 toString()
的呢?
在這裏,原型出現了. 首先, JavaScript 引擎檢查 studObj 是否存在 toString
方法?. 若是沒有找到,那麼它使用 studObj
的 __proto__
連接指向 Student函數
的 原型對象
. 若是它仍然沒法找到它那麼它會在往上層並檢查 Object 函數的原型對象,由於全部對象都是從 JavaScript 中的 Object 派生的,並查找 toString()
方法. 所以, 它在Object函數的原型對象中找到 toString()
方法,所以咱們能夠調用 studObj.toString()
.
查找方式,以下圖所示
上述就是原型基本知識點以及應用.