1、prototype與__proto__javascript
一、prototype(顯式原型):每個函數在建立以後都會擁有一個名爲prototype的屬性,這個屬性指向函數的原型對象。它只存在於函數裏,例以下面的例子中:java
function Person(name) { this.name = name; this.showMe = function() { alert(this.name); } }; Person.prototype.from = function() { alert('I come from prototype.'); } var p = new Person('js'); p.from();
Person擁有prototype對象,咱們向對象中添加了一個from方法,構造函數中有一個prototype的屬性,改屬性是一個指針,指向對應的prototype對象(注意區分一個是屬性一個是對象),這裏還有一個重要的屬性,就是prototype對象中有一個屬性constructor,該屬性指向對應的構造函數,是一種對應的關係。函數
p是Person構造函數新建的一個實例,new這個方法分爲3個部分,最重要的一步是第2步,就本例子來講 this
<1> var p={}; 也就是說,初始化一個對象p。spa
<2> p.__proto__=Person.prototype;prototype
<3> Person.call(p);也就是說構造p,也能夠稱之爲初始化p。3d
p這個對象沒有prototype屬性,可是有__proto__屬性,這個在下面會提到。指針
2、__proto__code
隱式原型,每個對象都擁有該屬性,上面提到新建的實例p,在實例化的時候,能夠得出p.__proto__=Person.prototype。那麼當咱們調用p.Say()時,首先p中沒有Say這個屬性, 因而,他就須要到他的__proto__中去找,也就是Person.prototype,而咱們在上面定義了 Person.prototype.Say=function(){}; 因而,就找到了這個方法。對象
具體的例子以下圖:
function Person(name) { this.name = name; this.showMe = function() { alert(this.name); } }; Person.prototype.from = function() { alert('I come from prototype.'); } function SubPer() {} SubPer.prototype = new Person('js'); var son = new SubPer(); son.showMe(); //js son.from(); //I come from prototype. alert(son.constructor);
代碼裏Person具備原型方法,SubPer經過SubPer.prototype = new Person('js')這句代碼實現了繼承,new的新實例son能夠獲取Person的方法。
function Person(name) { this.name = name; this.showMe = function() { alert(this.name); } }; Person.prototype = { //重寫原型 alertNum:function(){ alert(1111); } } function SubPer() {} SubPer.prototype = new Person('js'); var son = new SubPer();
咱們運行代碼,查看son.constructor的值,發現結果以下:
這兩個對象的constructor的值都指向了Function,由於咱們在這裏重寫了一個原型對象,每當新建立一個對象時,就會同時建立它的prototype對象,注意這裏的對象是由__proto__指向的,這個對象也得到了constructor屬性,對象字面量建立的對象其constructor指向Object,因此由Person new的實例,其constructor也指向了Object
代碼作以下的修改:
function Person(name) { this.name = name; this.showMe = function() { alert(this.name); } }; Person.prototype = { alertNum:function(){ alert(1111); } } function SubPer() {} SubPer.prototype = new Person('js'); SubPer.prototype.constructor = SubPer; //修改constructor var son = new SubPer();
constructor的值被修改成Suber構造函數,constructor的值能夠被修改覆蓋。