1.使用原型設置默認值
JavaScript是一種動態語言,它的對象系統也是動態的。在程序中,可以根據需要設置原型值,從而影響所有實例對象。如果為構造函數定義了與原型屬性同名的本地屬性,則本地屬性會覆蓋原型屬性,例如:
function p(x){//構造函數
this.x=x;
}
p.prototype.x=1;
var p1=new p(10);
alert(p1.x);//10,本地屬性覆蓋原型屬性
但原型屬性並沒有被刪除,它依然存在,僅是被同名的本地屬性覆蓋了,如果使用delete運算符刪除本地屬性,那麼原型屬性依然會顯示出來。因此,當原型屬性與本地屬性同時存在時,它們之間可以出現交流現象。利用這種現象為對像初始化默認值,例如:
function p(x){//構造函數
if(x)//如果參數存在,則使用該參數設置屬性,此條件是關鍵
this.x=x;
}
p.prototype.x=0;//利用原型屬性,設置本地屬性x的默認值
var p1=new p;
alert(p1.x);//0,顯示本地屬性的默認值
var p2=new p(1);
alert(p2.x);//1,顯示本地屬性的初始化值
2.使用原型實現數據備份
把本地對象的數據完全賦值給原型對象,相當於為該對像定義一個副本,這就是備份對象。當對像屬性被修改時,可以通過原型對像來恢復本地對象的初始值。下面示例演示了如何使用原型備份數據。
function p(x){//構造函數
this.x=x;
}
p.prototype.backup=function{//原型方法,備份本地對象的數據到原型對像中
for(var i in this){
p.prototype[i]=this[i];
}
}
var p1=new p(1);
p1.backup;//備份實例對像中的數據
p1.x=10;//改寫本地對象的屬性值
alert(p1.x);//10,說明屬性值已經被改寫
p1=p.prototype;;//恢復備份
alert(p1.x);//1,說明對象的屬性值已經被恢復到原始值
3.使用原型設置只讀屬性
利用原型還可以為對像屬性設置「只讀」特性,這樣可以避免對像內部數據被任意篡改。這裡的「只讀」只是一個表象,並不是真正禁止對像屬性進行修改,而是借助閉包體存儲屬性值,這樣就可以避免屬性值被動態修改。
下面示例演示了如何根據平面上兩點坐標來計算它們之間的距離。構造函數p用來設置定位點坐標,如果傳遞了兩個參數值,會返回以參數為坐標值的點;如果省略參數,則默認點為原點(0,0)。而在構造函數l中,通過傳遞的兩點坐標對像來計算它們的距離。
如果無意間修改了構造函數的方法b或e的值,則構造函數中length方法的計算值也隨之發生變化。這種動態效果對於動態跟蹤兩點坐標變化來說,是非常必要的。但是,我們並不需要在初始化實例之後隨意地改動坐標值,畢竟方法b和f與參數a和b是沒有多大聯繫的,但它們的參數值卻同時指向同一個對象的引用指針。
function p(x,y){//求坐標點構造函數
if(x)this.x=x;//初始x軸值
if(y)this.y=y;//初始y軸值
p.prototype.x=0;//默認x軸值
p.prototype.y=0;//默認y軸值
}
function l(a,b){//求兩點間距離的構造函數
var a=a;
var b=b;
var w=function{//計算x軸距離,返回對函數引用
return Math.abs(a.x-b.x);
}
var h=function{//計算y軸距離,返回對函數引用
return Math.abs(a.y-b.y);
}
this.length=function{//計算兩點間距離,使用小括號調用私有方法w和h
return Math.sqrt(w*w+h*h);
}
this.b=function{//獲取起點坐標對像
return a;
}
this.e=function{//獲取終點坐標對像
return b;
}
}
var p1=new p(1,2);//聲明一個點
var p2=new p(10,20);//聲明另一個點
var l1=new l(p1,p2);//實例化構造函數,傳遞兩點對像
alert(l1.length);//20.12461179749811,調用length方法計算兩點間距離
l1.b.x=50;//不經意地改動方法b的一個屬性為50
alert(l1.length);//43.86342439892262,說明上面改動影響到兩點間距離
為了避免因為改動方法b的屬性x的值而影響兩點間距離,可以在方法b和e中新建一個臨時性的構造類,設置該類的原型為a,然後實例化構造類並返回,這樣就阻斷了方法b與私有變量a的直接聯繫,它們之間僅是值的傳遞,而不是對對像a的引用,從而避免因方法b的屬性值變化而影響私有對象a的屬性值。
this.b=function{//方法b
function temp{};//臨時構造類
temp.prototype=a;//把私有對象傳遞給臨時構造類的原型對像
return new temp;//實例化後的對象,阻斷直接返回a所出現的引用關係
}
this.e=function{//方法f
function temp{};//臨時構造類
temp.prototype=a;//把私有對象傳遞給臨時構造類的原型對像
return new temp;//實例化後的對象,阻斷直接返回a所出現的引用關係
}
還有一種方法,這種方法是在為私有變量w和h賦值時,不是向函數賦值,而是函數調用表達式,這樣私有變量w和h存儲的是值類型數據,而不是對函數結構的引用,從而不再受後期相關屬性值的影響。
function l(a,b){//求兩點間距離的構造函數
var a=a;
var b=b;
var w=function{//計算x軸距離,返回函數表達式的計算值
return Math.abs(a.x-b.x);
}
var h=function{//計算y軸距離,返回函數表達式的計算值
return Math.abs(a.y-b.y);
}
this.length=function{//計算兩點間距離,直接使用私有變量w和h來計算
return Math.sqrt(w*w+h*h);
}
this.b=function{//獲取起點坐標對像
return a;
}
this.e=function{//獲取終點坐標對像
return b;
}
}
4.使用原型進行批量複製
先看下面一個示例:
function f(x){//構造函數
this.x=x;
}
var a=;
for(var i=0;i<100;i++){//使用for循環結構批量複製構造類f的同一個實例
a[i]=new f(10);//把實例分別存入數組
}
上面的代碼演示了如何複製同一個實例對像100次。如果後期需要修改數組中每個實例對象,就會非常麻煩。現在可以嘗試使用原型來進行批量複製操作,如下所示。
function f(x){//構造函數
this.x=x;
}
var a=;
function temp{};//定義一個臨時的空構造類temp
temp.prototype=new f(10);//把構造類f實例化,並把該實例傳遞給構造類temp的原型對像
for(var i=0;i<100;i++){;//使用for循環結構批量複製臨時構造類temp的同一個實例
a[i]=new temp;//把實例分別存入數組
}
把構造類f的實例存儲在臨時構造類的原型對像中,然後通過臨時構造類temp實例來傳遞複製的值。因此,要想修改數組的值,只需要修改類f的原型即可,從而避免逐一修改數組中每個元素。