1: <script>
2: function Circle( radius ){
3: this.r = radius;
4: this.des = "圓形";
5:
6: this.showInfo = function(){
7: alert("這是一個"+this.des);
8:
9: }
10: }
11:
12: function Circle_area(r){ return Circle.PI*this.r*this.r; }
13:
14: function Circle_perimeter(r){ return 2*Circle.PI*r;}
15:
16: Circle.PI = 3.14;
17: Circle.perimeter = Circle_perimeter;
18: Circle.prototype.area = Circle_area;
19:
20: var c = new Circle(3);
21:
22: //測試類別屬性
23: //alert(Circle.PI )//3.14
24: //alert(c.PI)//undefined 因為類屬性是和類本身,也就是函數本身相關聯的,和類執行個體沒有直接關係。
25: //alert(c.constructor.PI)//3.14 如果想通過類執行個體訪問類屬性,那麼就需要先訪問該執行個體的建構函式,進而訪問該類屬性
26: //alert(Circle.des)//undefined 因為函數Circle函數中的this.des中的this指代的不是函數本身,而是調用r的對象,而且只能是對象。
27: //alert(c.des)//圓形 this此時為執行個體化的 對象c。
28:
29: /*結論:
30: 物件導向的角度:類屬性是類對象的直接屬性,且該屬性與基於該類對象產生的執行個體對象沒有直接關係,無法直接調用。
31: 可以直接通過 類名.屬性名稱 調用該類屬性。如果想通過該類對象的執行個體對象調用類屬性,那麼可以使用 對象執行個體.constructor屬性
32: 調用該對象的類對象,然後通過類對象調用其類屬性
33: javascript函數角度:類屬性是javascript函數對象的直接屬性變數(這裡之所以稱之為屬性變數是由於javascript變數和屬性的同一
34: 性),且該屬性變數與基於該函數物件建構出來的對象引用(產生了一個對象,這個對象實際上是一個Null 物件,並且儲存了對構造
35: 函數以及建構函式初始化時函數內部this關鍵字下的相關屬性和函數的引用[c.prototype和建構函式中this.下面的相關屬性、函數]:)
36: 沒有直接關係,如果想通過基於建構函式產生的對象c調用建構函式對象的屬性變數PI,那麼需要通過c.constructor屬性找到該構造
37: 函數對象,並通過該對象擷取其屬性變數。
38: */
39:
40: //測試類別方法
41: //alert(Circle.perimeter(3)); //18.4 直接調用函數的類方法。
42: //alert( c.perimeter(3) ); //FF:c.perimeter is not a function IE:對象或屬性不支援此方法。因為perimeter函數是Circle類的類方法,和執行個體對象沒有直接關係
43: //alert(c.constructor.perimeter(3));//18.84 調用該物件建構函數(類函數)的方法(函數)。
44: //alert(c.area(3))//28.25.... Circle類的prototype原型屬性下的area方法將會被Circle類的執行個體對象繼承。
45: //alert(Circle.area(3));//FF: 錯誤: Circle.area is not a function 因為area方法是Circle類的原型屬性的方法,並不是Circle類的直接方法。
46:
47: //結論:同上,把屬性換成了方法,把屬性變數換成了函數。
48:
49: //測試prototype對象屬性
50: //alert(c.prototype); //undefined 執行個體對象沒有ptototype屬性
51: //alert(Circle.prototype); //object Object
52: //alert(Circle.prototype.constructor)//返回Circle的函數體(函數代碼體),相當於alert(Circle)
53: //alert(Circle.prototype.area(3));//NaN 方法調用成功,但是返回結果卻是NaN,原因是area函數內部的this.r是undefined。
54: //alert(Circle.prototype.PI) //undefined因為PI屬性是Circle類函數的直接屬性,並不會在prototype屬性下存在
55: //alert(Circle.prototype.constructor.PI)//3.14 通過Circle類的原型對象調用該原型對象的建構函式(類函數),再通過類函數調用PI屬性。
56:
57: /*結論:prototype原型對象是javascript基於原型鏈表實現的一個重要屬性。
58: Javascript角度:1. 執行個體對象沒有prototype屬性,只有建構函式才有prototype屬性,也就是說建構函式本身儲存了對prototype屬性
59: 的引用。。2. prototype屬性對象有一個constructor屬性,儲存了引用他自己的建構函式的引用(看起來像是個迴圈:A指向B,B指向A...)
60: 3.prototype對象(不要被我這裡的屬性對象,對象,對象屬性搞暈乎了,說是屬性對象,就是說當前這個東西他首先是某個對象的屬性,
61: 同時自己也是個對象。對象屬性就是說它是某個對象的屬性。)的屬性變數和屬性對象將會被該prototype對象引用的建構函式所建立的
62: 對象繼承(function A(){} A.prototype.pa = function(){} var oA = new A(); 那麼oA將會繼承屬性函數pa)。
63: */
64:
65: /*這裡對 對象屬性,對象方法不再做詳細測試。
66: 1.javascript對象執行個體的在通過其建構函式進行執行個體化的過程中,儲存了對建構函式中所有this關鍵字引用的屬性和方法的引用(這裡不
67: 討論對象直接量文法的情況)。但如果建構函式中沒有通過this指定,對象執行個體將無法調用該方法。2.javascript可以通過建構函式建立
68: 多個執行個體,執行個體會通過__proto__屬性繼承原型對象的屬性和方法。如果對執行個體對象的屬性和方法進行讀寫操作,不會影響其原型對象的
69: 屬性和方法,也就是說,對於原型對象,javascript執行個體對象只能讀,不能寫。那當我們對執行個體對象的屬性和方法進行修改的時候也可以
70: 改變其值這是為什麼呢?其實當我們試圖在執行個體對象中使用繼承自原型對象的屬性或方法的時候,javascript會在我們的執行個體對象中複
71: 制一個屬性或方法的副本,這樣,我們操作的時候,其實操作的就是執行個體對象自己的屬性或方法了。
72:
73:
74: */
75: //測試__proto__屬性
76: //alert(c.__proto__)//FF:object IE8:undefined 該屬性指向Circle.prototype,也就是說調用該對象將會返回Circle的prototype屬性。
77: //由於IE8及以下版本不支援__proto__屬性,所以以下結果都在FF下得出。
78: //alert(c.__proto__.PI)//undefined 因為函數原型下面沒有PI屬性,PI是類函數Circle的直接屬性
79: //alert(c.__proto__.area(3))//NaN 該函數執行成功,傳回值為NaN是由於函數體中的this.r為undefined。
80:
81: /*結論:__proto__屬性儲存了對建立該對象的建構函式引用prototype屬性的引用,也就是說建構函式可以引用prototype,基於該構
82: 造函數產生的執行個體也可以引用,只不過引用的方式不一樣。*/
83: </script>