前言
什么是原型?
原型,漢語詞語,讀音為yuán xíng。指原來的類型或模型,特指文學藝術作品中塑造人物形象所依據的現實生活中的人。
狹義上將是原型人物。通常這樣的解釋,往往我們會覺得原型與產品之間,是在原型上破壞性的加工。
如果這樣理解的話,那么將會對js的原型理解艱難,因為英文翻譯過來是抽象的。
js的原型是擴展的意思,就像我們學數據結構的雙向鏈表一樣。
也就是說原型是擴展的對象的一個屬性。
那么什么是原型鏈?
原型鏈指的是指向原型的這條連接,直到指向null為指,因為這個時候鏈接就斷了。
好的概念理解完了,開始正文吧。下面理解,均為個人理解,如有不對望指出。
正文
上面寫道擴展對象的一個屬性指向了原型,那么這個屬性是什么?
是__proto__。
proto 與 prototype
看一段代碼:
var obj= new Object();
consoleProto(obj);
function consoleProto(obj){
if(obj!=null)
{
console.log(obj.__proto__);
consoleProto(obj.__proto__);
}
}
上文我通過遞歸的方式,把原型鏈打印了出來。
也就是說我創建一個對象,都會有一個屬性__proto__指向另外一個對象。
現在我不關心null,我更關心的是紅框中的對象到底是啥?
接來下我寫了另一段代碼:
var obj= new Object();
var obj2=new Object();
console.log(obj.__proto__===obj2.__proto__);
返回的結果為:true。
這個說明什么呢?說明任何一個對象的原型最終會基於一個公共原型對象。
也就是說new Object() 會把一個新的對象增加一個公共的對象引用。
那么new Object()是如何獲取這個對象的呢?調用了什么函數可以獲取到這個對象?或者說Object本身就帶有這個公共屬性?
我寫下了另外一段代碼:
<script>
var obj= new Object();
console.log(Object.prototype===obj.__proto__);
</script>
結果為true。
原來Obect本身就帶有這個屬性。
那么再往上推,Object是什么,Object是一個函數。
把Object 打印出來,然后提出疑問是否每個函數都具有prototype 屬性?
function Object1(){
}
console.log(prototype);
console.log(Object1.prototype==Object.prototype);
打印出來是prototype 有值,后面的結果為false。
證明了每個函數,都具有prototype,但是Object比較特殊,其Object內置函數。
他們的關系如下:
console.log(Object1.prototype.__proto__==Object.prototype);
那么現在單獨討論Object1,Object1是一個函數但是同時也是一個對象,那么從對象的角度來看下,對象想到的是__proto__.
function Object1(){
}
console.log(Object1.__proto__==Function.prototype);
得出的結果為true。
如圖:
那么上圖中的原型對象是否就是原始對象。有兩種方法可以證明一種就是沒有原型,一種就是和原始對象做對比。
console.log(Object1.__proto__==Object.prototype);
我采用第二種,結果不是。同時說明Fuction 不是 Object的構造函數。
實際上是這樣的:
console.log(Function.prototype==Function.prototype);
console.log(Function.prototype.__proto__==Object.prototype);
兩者都為true。
上述結論圖:
其中內置方法沒有prototype,所以不是每個函數都有prototype。
再次__proto__ 與 prototype
上述提及的是內部的對象關系,那么我們書寫的時候不用理會這么多了。
function Tree(){
}
var newtree=new Tree();
console.log(newtree.__proto__==Tree.prototype);
關系為:
constructor
既然構造函數能夠知道原型,原型是否能夠知道構造函數,也是可以的。
console.log(Tree==Tree.prototype.constructor);
兩者相生相伴,一起出生。
為什么說原型鏈可以實現繼承?
function Tree(){
}
Tree.prototype.name="白楊樹";
var newtree=new Tree();
console.log(newtree.name);
這時候打印出來的是“白楊樹“。也就是說如果newtree找不到,則會去根據原型鏈找原型,一直找下去,知道找到為止。
同樣:
console.log(newtree.contructor==Person);
也就是因為newtree沒有這個屬性,只好找原型了。
最后一筆
console.log(Tree.prototype.__proto__.constructor);
修改一下:
總結
以上皆為個人理解,如有不對,望請指點。