原型原型鏈學習記錄
這是一篇學習筆記。
個人心得:
關於原型和原型鏈這一塊,很難,但是,一旦理解,就通了。
對於這一塊,我之前不懂的時候,非要去弄明白,特別痛苦,之後,看到了王福朋老師的閉包原型系列,真的是茅塞頓開!看完之後,我就拿起JavaScript高程3,高程3第6章節,耐心跟著看也就明白了。之後,再去做一些圖解,如果能夠根據繼承畫出所有的關係,沒有矛盾的點,那就基本沒問題了。再到網上找差不多的文章看,如果沒有衝突點,那這一塊就沒問題了。
參考的內容:
你不知道的JavaScript 上
JavaScript高級程序設計 3
內容:
一些名詞的解釋 +幾個圖解(所以圖片會比較多) 。
1:簡單的實例
2:完整的實例
3:重寫原型對象
4:原型繼承
原型/繼承
JavaScript中的對象都有一個內置屬性 [[prototype]]屬性。在表示的時候可以用__proto__表示。
__proto__: 每個對象都有這樣一個屬性,指向該對象的構造函數的prototype的指向。
所有原型鏈的最後指向都是null。
除了Object.create,無實參直接創建的對象的原型是null/沒有原型,即不繼承任何屬;其餘的對象的原型鏈上null之前都有一個Object.prototype原型對象。
Object的prototype對象的[[prototype]]內部屬性的值是null。即:Object.prototype.__proto__ === null //true。
所有通過對象直接量創建的對象都有一個共同的原型對象:Object.prototype
通過關鍵字new和構造函數調用創建的對象的原型就是構造函數的prototype屬性所指向的對象。
(當通過new和構造函數生成實例,實例的原型對象就會鎖定)。
JavaScript中的內建函數以及用戶自定義函數都是通過Function 這個函數創建的。
所有的函數默認都會擁有一個名為prototype的不可枚舉的屬性。這個屬性指向一個對象,被稱為這個函數的原型對象。
每個原型有一個不可枚舉的屬性constructor。這個屬性引用的是對象關聯的函數,即constructor屬性的值是一個函數對象。
而Function是由它自己創建的,所以:
Function.__proto__ === Function.prototype ; // true;
new 調用構造函數的一個重要特徵:
構造函數的prototype屬性值被用做新對象的原型。即通過同一個構造函數創建的對象都繼承自同一個對象。
構造函數,原型對象,實例它們都是對象!
instanceof:左邊走__proto__,右邊走prototype,如果能重合,返回true,否則,返回false。
A instanecof B,一般,A是一個函數,B是一個對象。
使用new的構造函數調用會生成prototype和constructor引用。
如何理解函數,對象,實例,原型,構造函數之間的關係,圖解是非常好的方式,所謂有圖有真相。
可以通過原型鏈(通過__proto__串在一起的原型形成了一條鏈)把它們串在一起理解。
1:
function Foo{ /*...*/}
var a1=new Foo;
var a2=new Foo;
這是一個非常簡單的構造函數和實例對象。
這樣,它們的關係圖就出來了。
實例a1,a2,函數Fun1,原型Fun1.prototype,都是對象.。
函數Fun1有一個prototype屬性,指向一個對象,名為Fun1.prototype,成為Fun1的原型對象。
原型對象Fun1.prototype有一個constructor屬性,指向該對象關聯的函數。
實例a1,a2都有一個__proto__,指向該實例的構造函數的prototype的指向,並且它們指向的是同一個原型對象,因為a1,a2都是通過new和Fun1構造函數調用生成的實例。
這個圖是比較基本的,並沒有展現所有的關係,下一張圖會進一步展現它們的關係。
2:
對象都有[[prototype]]屬性,屬性值為該對象構造函數的prototype值。
上面的構造函數,原型對象,實例,都是對象,所以它們都有[[prototype]]屬性,即它們都繼承自某一原型。
其中null不是實例,null是空對象,什麼都沒有。
因為函數Fun1是用戶自定義函數,Object,Function是內置函數,都是函數,所以就是通過Function 函數創建的,所以,它們的原型就是Function.prototype.
Function.prototype.上有call和apply方法,所有的函數都繼承自它,所以,所有的函數都能夠擁有這兩個方法。
因為:除了Object.create,無實參直接創建的對象的原型是null/沒有原型,即不繼承任何屬;其餘的對象的原型鏈上null之前都有一個Object.prototype原型對象。
所以,原型對象和實例的原型都指向了Object.prototype。
3重寫原型對象 :
function Foo{/*...*/}
var a1=new Foo; //用new調用之後就會鎖定原型
Foo.prototype={/*...*/}; //創建一個新原型對象,重寫Foo的prototype
var a2=new Foo;
圖3:
註:
新的Foo.prototype 就是Object的實例。
舊的Foo.prototype 不會消失,依然會存在。因為實例a1的原型會指向它,實例a1繼承它,在通過new調用生成實例的時候,a1就會鎖定它的原型。
Foo.prototype.constructor === Object; //true
a2.constructor === Object; //true
但是,實際上Foo.prototype和a2都沒有constructor屬性,它們都是繼承自Object.prototype。原型才有constructor這個屬性,其他對象的constructor都是繼承自原型。
4:繼承
function SuperType{
this.property=true;
}
SuperType.prototype.getSuperValue=function{
return this.property;
};
function SubType{
this.subproperty=false;
}
SubType.prototype=new SuperType; //繼承自SuperType /重寫了原型
SubType.prototype.getSuperValue=function{
return this.subproperty;
};
var instance=new SubType;
(這張圖片源自高程3)
這裡也可以比較清楚地看到對象的關係和對象所擁有的屬性集合。
這是一個簡單的原型繼承,通過圖解關係就可以看到上面代碼,方便理解。
舊的SubType.prototype 依然存在,不過這裡它沒有實例去引用它。新的SubType.prototype 是作為SuperType的實例存在,繼承自SuperType.prototype 。
從instance開始,通過__proto__連接,直到null,就形成了一條原型鏈,上層的屬性會被下層繼承。
以上就是我的理解,如果有錯誤,還請各位前邊指正,謝謝。
※JStorm與Storm源碼分析(四)——均衡調度器,EvenScheduler
※編寫使用多線程的希爾排序(shell sort)
※ABP從入門到精通(2):aspnet-zero-core 使用MySql資料庫
TAG:科技優家 |
※上衣原型與袖原型的紙樣設計
※日本文化原型——第七代上身原型
※歷史原型挖掘系列
※從模型到原型
※貓為原型 紙藝作品
※JS學習筆記 對象、包裝類、原型、原型鏈、命名空間、對象枚舉
※史努比的原型
※童裝原型製版教程
※大事件人物原型!
※我首台多通道原子磁力計新型腦磁圖原型機研製成功
※服裝打版-男裝上衣原型與袖原型
※誰是穆桂英的歷史原型
※EOS增材製造助力新型印刷電路板原型
※我國首台多通道原子磁力計新型腦磁圖原型機研製成功
※初學紙樣必讀—服裝工業女裝原型推板
※「龍」的原型是蟒蛇
※《諾亞方舟漂流記》中草原獵貓的原型
※10大經典電影角色與歷史原型人物對比:鋼鐵俠的原型原來是他
※《海賊王》30位人物原型大揭秘!路飛的原型原來是他
※六片法女裝原型