對象基礎
- 封裝 --- 把相關資訊(無論資料或方法)儲存在對象上的能力;
- 聚集 --- 把一個對象儲存在另一個對象上的能力;
- 繼承 --- 有另一個類(或多個)得來類的屬性和方法的能力;
- 多態 --- 編寫能以多種方法啟動並執行函數或方法的能力.
1.工廠方式
var oSite = new Object;oSite.name="noyobo";oSite.url = "http://noyobo.cnblogs.com/";oSite.showName = function(){ alert(this.name);};
此代碼建立對象 oSite,接著設定了幾個屬性.它的名字是noyobo ,連結是 http://noyobo.cnblogs.com/ showName 屬性是指向函數的指標. 那麼這個屬性就是一個方法.如果要建立多個 site 執行個體怎麼辦呢?
建立並返回特定類型對象,工廠函數(factory function)
function creatSite(){ var oTempSite= new Object; oTempSite.name="noyobo"; oTempSite.url = "http://noyobo.cnblogs.com/"; oTempSite.showName = function(){ alert(this.name); }; return oTempSite;}var oSite1 = new creatSite();var oSite2 = new creatSite();
把程式碼封裝含在 creatSite() 函數中. 最後一行代碼 採用 return oTempSite; 返回該函數值.
建立的 oSite1 和 oSite2 都具有相同的屬性和方法. 我們還可以給它傳入值
function creatSite(sName,sUrl){ var oTempSite= new Object; oTempSite.name = sName; oTempSite.url = sUrl; oTempSite.showName = function(){ alert(this.name); }; return oTempSite;}var oSite1 = new creatSite("baidu","wwww.baidu.com");var oSite2 = new creatSite("google","www.google.cn"); oSite1.showName(); // 輸出 "baidu"oSite2.showName(); // 輸出 "google"
給函數 creatSite() 函數加上參數,就可以建立 具有相同屬性與方法.卻有不同的值.
可這樣每建立一個 creatSite() 對象 就建立了一個 showName() , 實際他們共用使用了這一函數.(避免記憶體浪費) 我們可以這麼寫
function showName(){ alert(this.name) // this 總是指向調用該函數的對象}function creatSite(sName,sUrl){ var oTempSite= new Object; oTempSite.name = sName; oTempSite.url = sUrl; oTempSite.showName = showName; return oTempSite;}var oSite1 = new creatSite("baidu","wwww.baidu.com");var oSite2 = new creatSite("google","www.google.cn"); oSite1.showName(); // 輸出 "baidu"oSite2.showName(); // 輸出 "google"
這樣 oSite1 和 oSite2 就共用使用了 showName() 方法.
但是這樣看. showName() 並不是 creatSite() 對象的一個方法,我們可以採用 建構函式的方 來建立.
2.建構函式方式
函數名既為類名 類名採用首字母大寫. 這是一個好習慣.用於區分其他類型,也與本機物件(Object String Number ... )保持一致
function Site(sName,sUrl){ this.name = sName; this.url = sUrl; this.showName = function(){ alert(this.name); }}var oSite1 = new Site("baidu","wwww.baidu.com"); var oSite2 = new Site("google","www.google.cn"); oSite1.showName(); // 輸出 baiduoSite2.showName(); // 輸出 google
和工廠方式很相似,值是函數內部使用 this 關鍵字 使用 new 運算子 後就建立了一個對象,並使用this才能訪問此對象, 函數內部也不需要 使用 return 放回.預設情況下 建構函式的傳回值就是 this . 這裡又回了前面提到的 問題. 每個 new 對象 都建立了一個 showName() ;
3.原型方式
該方式使用對象的 prototype 屬性.可以看成是建立對象所以來的原型. 重寫上面的執行個體
function Site(){};Site.prototype.name = "baidu";Site.prototype.url = "www.baidu.com";Site.prototype.showName = function(){ alert(this.name);};
var oSite1 = new Site(); var oSite2 = new Site(); oSite1.showName(); // 輸出 baiduoSite2.showName(); // 輸出 baidualert(oSite1 instanceof Site) // 輸出 true oSite1 是 Site()的一個物件類型. 使用原型方式還可以使用 instanceof 運算子檢查
這段代碼,先定義建構函式 Site() 並沒有任何代碼. 接下來通過 prototype 添加 Site 的屬性 和方法. 從語義上看所有的屬性和方法都屬於一個對象.
函數共用上不會存在問題.可是這裡不能使用參數初始化的值. 必須在對象建立之後才能改變值. 考慮下面的例子
function Site(){};Site.prototype.name = "baidu";Site.prototype.url = "www.baidu.com";Site.prototype.area = new Array("beijing","hangzhou");Site.prototype.showName = function(){ alert(this.name);};var oSite1 = new Site(); var oSite2 = new Site(); alert(oSite1.area); // 輸出 beijing,hangzhoualert(oSite2.area); // 輸出 beijing,hangzhouoSite1.area.push("shanghai");alert(oSite1.area); // 輸出 beijing,hangzhou,shanghaialert(oSite2.area); // 輸出 beijing,hangzhou,shanghai
看到 oSite1.area 屬性 添加"shanghai" 之後. oSite1.area 改變了. 可是 oSite2.area 也跟著改變了.
這裡屬性 area 是指向 Array 對象的指標. 該數字包含兩個地名"beijing" 和"hangzhou". area 都是引用值.(如原廠模式的第四個例子) Site 的兩個實力都是指向同一個數組的,所以改變其中一個.在另一個也能看到. 那我們該如何建立對象的方法呢? 聰明的你可能已經想到了.
3.混合的建構函式/原型方式
重寫上面的例子
function Site(sName,sUrl){ this.name = sName; this.url = sUrl; this.area = new Array("beijing","hangzhou");};Site.prototype.showName = function(){ alert(this.name);};var oSite1 = new Site("baidu","wwww.baidu.com"); var oSite2 = new Site("google","www.google.cn"); alert(oSite1.area); // 輸出 beijing,hangzhoualert(oSite2.area); // 輸出 beijing,hangzhouoSite1.area.push("shanghai");alert(oSite1.area); // 輸出 beijing,hangzhou,shanghaialert(oSite2.area); // 輸出 beijing,hangzhou
現在看起來更像建立一個對象了.所有的屬性都在建構函式中建立.我們又可以用參數設定預設值了.並且只建立了一個 showName() 方式.沒有造成記憶體浪費.
我們再視覺上封裝有一下.也讓結構看起來更緊湊
function Site(sName,sUrl){
this.name = sName;
this.url = sUrl;
this.area = new Array("beijing","hangzhou");
if(typeof Site._initialized == "undefined"){
Site.prototype.showName = function(){
alert(this.name);
};
//alert("我只運行了一次");
Site._initialized = true;
};
};
var oBaidu = new Site("baidu","www.baidu.com");
var oGoogle = new Site("google","www.google.cn");
oBaidu.showName()
至於使用哪種方式,可能實際中的理解了.不過不要單獨使用建構函式 或者 原型方式!