深刻探究JavaScript對象系列(五)

       以前比較忙,再加上家裏發生了些不開心的事情,也就沒什麼心情看書,昨天加了一天班,今天終於能夠靜下心來寫點東西html

一.類和原型

       在JavaScript中,類的全部實例對象都從同一個原型對象上繼承屬性,所以原型對象是類的核心,這個在以前幾篇中已經提到過,如今咱們來看兩個例子,着兩個例子實現了一樣的效果:函數

 1 例一:
 2 function inherit(p){ /;/這個函數是用來建立對象的,以前已經寫到過了
 3     if(p == null) throw TypeError(); 
 4     if(Object.create) return Object.create(p);  
 5 
 6     var t = typeof p;
 7     if(t !== "object" && t !== "function") throw TypeError();
 8     function F(){};
 9     f.prototype = p;
10     return new F();
11 }
12 
13 range.methods = {
14     includes : function(x){
15         return this.from <= x && x <=this.to;
16     },
17 
18     toString : function(){
19         return "this is form "+this.from+" to "+this.to;
20     }
21 }
22 
23 function range(from,to){
24     var r = inherit(Range.methods);
25     r.from = from;
26     r.to = to;
27     return r;
28 }
29 var r = range(1,9);
r.includes(3); //返回true 30 //例二 31 function Rnage(from,to){ 32 this.from = from; 33 this.to = to; 34 } 35 36 Range.prototype = { 37 includes : function(x){ 38 return this.from <= x && x <=this.to; 39 }, 40 41 toString : function(){ 42 return "this is form "+this.from+" to "+this.to; 43 } 44 }
  var r = new Range(1,9);
r.includes(22);//返回false

       上述兩個例子實現了一樣的效果,例一中定義了一個工廠方法range(),用來建立新的範圍對象,要注意的地方是range函數給每一個範圍對象都定義了from屬性和to屬性,這兩個屬性是非共享的,固然也是不可繼承的。(用這種方式來建立新對象的方法不常見)測試

       例二中使用瞭如今常常看到的利用構造函數來建立對象的方法,調用構造函數的一個重要特徵是,構造函數的prototype屬性被用來作新對象的原型。this

  原型對象是類的惟一標誌:當且僅當兩個對象繼承自同一個原型對象時,他們才屬於同一個類的實例,舉個例子來講,當使用instanceof來檢測一個對象是否爲給定類的實例時,如r instanceof Range,js引擎不是檢查r是不是由Range()函數來建立,而是檢查r的原型對象是否是Range.prototype.spa

二.constructor屬性

  先看下下面這張圖prototype

  任何一個JavaScript函數均可以用來看成構造函數(但每每不會正常工做),而且調用一個構造函數是要用到函數的prototype函數的,所以除了ECMAScript5中的Function,bind()方法返回的函數外,每個js函數都自動擁有一個prototype屬性,這個屬性也是一個對象包含一個惟一不可枚舉的constructor屬性,這個屬性的值是一個函數對象(var F = function(){};),js正式用這個屬性來只帶它們的構造函數,用代碼的方式來表現就是像下面這個樣子3d

1 var p = F.prototype;
2 var c = p.constructor;
3 c === F;       //返回true

或者是像下面這樣:code

1 function F(){};
2 var o = new F();
3 o.constructor === F;  //返回true

  可能會有人拿上一節中的例二來測試constructor,結果發現是不對的,爲何不對呢?那是由於例二中Range.prototype被重寫了,它根本就沒有constructor屬性,那怎麼補救呢,很簡單,能夠這樣寫:orm

 1 //方法一
 2 Range.prototype = {
 3         constructor : Range, //顯式地指定constructor值
 4     includes : function(x){
 5         return this.from <= x && x <=this.to;
 6     },
 7 
 8     toString : function(){
 9         return "this is form "+this.from+" to "+this.to;
10     }
11 }
12 
13 //方法二
14 Range.prototype.includes = function(x){
15         return this.from <= x && x <=this.to;
16 }
17 Range.prototype.toString = function(x){
18        return "this is form "+this.from+" to "+this.to;
19 }

  關於原型繼承和constructor,推薦你們看看這個http://www.cnblogs.com/sanshi/archive/2009/07/08/1519036.html,看完會有更深的理解。htm

相關文章
相關標籤/搜索