2014-5-4閱讀490 評論0 javascript
最近在學習javascript的原型,發現了__proto__與prototype,學問很大,因而研究了一下。 java
首先解釋一下什麼是原型? chrome
原型是一個對象,其餘對象能夠經過它實現屬性繼承。 數組
對象又是什麼呢? 瀏覽器
在javascript中,一個對象就是任何無序鍵值對的集合,若是它不是一個主數據類型(undefined,null,boolean,number,array,string),那它就是一個對象。 函數
那麼如何查看一個對象的原型是啥呢?又如何給一個對象設置原型呢? 學習
標準對象原型訪問器Object.getPrototype(object),到目前爲止只有Firefox和chrome實現了此訪問器。除了IE,其餘的瀏覽器支持非標準的訪問器__proto__,而prototype則是一個只有函數才具備的屬性, 測試
也就是說,若是這個對象不是函數,那麼它就沒有prototype這個屬性。 this
下面代碼證明了以上結論。 spa
<script> var a={name:'derek'}; var b=function(name){ name=this.name; }; document.write(a.prototype+"<br>");//undefined 對象a顯然不是一個函數,因此沒有prototype這個屬性。 document.write(Object.getPrototypeOf(a)+"<br>");//[object Object] document.write(Object.getPrototypeOf(b)+"<br>");//function Empty() {} document.write(Object.getPrototypeOf(b)==b.__proto__);//true 這兩個的是等價的,只不過瀏覽器的兼容型不一樣。 </script>
再說一下javascript的構造函數
一、構造函數和普通的函數同樣,可是具備如下兩個特殊性質。
二、一般構造函數的首字母是大寫的(讓識別構造函數變得更容易)。構造函數一般要和 new 操做符結合,用來構造新對象。
下面這個例子很厲害~
基於所知道的知識,請想象建立一個新的對象,並讓新對象表現地像數組的過程。一種方法是使用下面的代碼。
1
2
3
4
5
6
|
// 建立一個新的空對象
varo = {};
// 繼承自同一個原型,一個數組對象
o.__proto__ = Array.prototype;
// 如今咱們能夠調用數組的任何方法...
o.push(3);
|
雖然這段代碼頗有趣,也能工做,可問題在於,並非每個 JavaScript 環境都支持可寫的 __proto__ 對象屬性。幸運的是,JavaScript 確實有一個建立對象內建的標準機制,只須要一個操做符,就能夠建立新對象,而且設置新對象的 __proto__ 引用 – 那就是「new」操做符。
1
2
|
varo =newArray();
o.push(3);
|
JavaScript 中的 new 操做符有三個基本任務。首先,它建立新的空對象。接下來,它將設置新對象的 __proto__ 屬性,以匹配所調用函數的原型屬性。最後,操做符調用函數,將新對象做爲「this」引用傳遞。若是要擴展最後兩行代碼,就會變成以下狀況:
1
2
3
4
|
varo = {};
o.__proto__ = Array.prototype;
Array.call(o);
o.push(3);
|
函數的 call 方法容許你在調用函數的狀況下在函數內部指定「this」所引用的對象。固然,函數的做者在這種狀況下須要實現這樣的函數。一旦做者建立了這樣的函數,就能夠將其稱之爲構造函數。
咱們來測試一下,
var Person=function(name,age){ this.name=name; this.age=age; document.write("hello,I'm "+name+" and "+age+" years old"+"<br>"); } var p1=new Person('derek',23); document.write(Object.getPrototypeOf(p1)==Person.prototype);//true document.write(p1.__proto__==Person.prototype);//true 兩種訪問對象原型的方式會獲得相同的結果,前提是非IE六、七、8瀏覽器。。能夠上面的理論是正確的~
咱們接着作實驗,看一下繼承是怎麼實現的~
var Person=function(name,age){ this.name=name; this.age=age; document.write("hello,I'm "+name+" and "+age+" years old"+"<br>"); } Person.prototype.smile=function(){ document.write("O(∩_∩)O~"+"<br>"); } var p1=new Person('derek',23); p1.smile();
首先,p1這個對象沒有smile這個函數,因而去__proto__屬性上去找,由於p1.__proto__==Person.prototype,而Person.prototype上剛好有這個函數,所以就會出現上面的運行結果。這個是最簡單的原型鏈,若是Person.prototype上尚未smile()這個函數,那麼就會去Person.__proto__去繼續找,依次類推。