學習JS

Jarrett.zhou發表於2014-03-05

原型是Js中非常重要的概念,每個函式(在Js裡面函式也是物件)都有一個叫prototype即原型)的屬性,不過在一般情況下它的值都是null,但它他有一項非常重要的功能就是所以例項都會共享它裡面的屬性和方法(這就是Js裡面實現繼承的基礎)!
還是舉例吧:

 function auth(){
  alert(this.name);
  //此處一定要加this關鍵字
 }
 auth.prototype.name='shiran';//這句可以放到物件定義之後,但必須在被呼叫之前
 new auth();//這裡一定要用new

這裡需要注意三點:
 第一、name前面一定要加關鍵字this,不然的話就會得不到任何,因為如果你不加this,他就不會到原型中查詢(加上this是屬性它會在上下文查詢,看看前面我講的變數的查詢那一章)。
 第二、如果例項物件在物件中找不到屬性或方法就會到物件的prototype中去查詢,所以如果想在函式被呼叫的時候呼叫物件的屬性或方法,就必須把呼叫語句放在prototype定義之後(在這裡,就是new auth必須放到auth.prototype.name之後)!
 第三、只有例項物件才會到原型中查詢,因為對於原物件來說prototype是他的屬性必需通過prototype才能訪問(在這裡,要用new auth()生成一個例項,而不能用auth)!

原型對於物件的例項來說是共享的,這既給程式帶來方便,同時也會讓人感到迷惑,出現好多讓人意想不到的結果!
 auth=function(){ };
 auth.prototype={
  name:[],
  getNameLen:function(){
   alert(this.name.length);
  },
  setName:function(n){
   this.name.push(n);
  }
 }

 var lwx=new auth();
 lwx.setName('lwx');
 lwx.getNameLen();
 var shiran=new auth();
 shiran.setName('shiran');
 shiran.getNameLen();
第二次彈出的對話方塊顯示name的長度已經是2,為什麼呢?這就是原型的共享引起的,因為變數lwx和shiran都是auth物件,而且name屬性是在auth物件的原型中定義的,所以lwx和shiran例項之間共享name這個屬性!!可是這並不是我們想要看到的結果,因為我們希望,每個例項之間是相互隔離的。
這裡我們可以把name屬性從原型中去掉,放在auth物件的定義中即:

 auth=function(){
  this.name=[];//切記,一定要在前面加上this關鍵詞
 };
這樣一來,每個auth的例項都會擁有自己的name屬性!所以推薦大家,以後在定義物件的時候:把屬性放到定義裡,而把物件的方法放到原型裡!