1. 程式人生 > >JS 建立物件的幾種方式

JS 建立物件的幾種方式

<script type="text/javascript">

/* 建立物件的幾種方式: */

// 1. 工廠方法:能建立並返回特定型別物件的工廠函式(factory function).
function createCar(sColor){
   
var car =new Object();   // 或者 var car = new Object ;// 物件屬性    car.color = sColor ;      
   
// 物件方法
    car.showColor =function (){   
        alert(
123);
    }
 ;    // 記住,這裡一定要用 ; 表示結束
return car;// 這裡是 return car ; 而不是 return this.car ; 因為 this.car 為 undefined}

/* 
  呼叫此函式時,將建立物件,並賦予它所有必要的屬性,使用此方法建立 car 物件的兩個版本,
  ( oCar1 和 oCar2 ) ,他們的屬性完全一樣。
  使用此方法存在的問題:
  1. 語義上看起來不像使用帶有建構函式的 new 運算那麼正規.
  2. 使用這種方式必須建立物件的方法。每次呼叫 createCar(),都要建立 showColor(),意味著每一個物件
  都有自己的 showColor 版本,事實上,每一個物件都共享了是同一個函式.
  有些開發者在工廠函式外定義物件的方法,然後通過屬性指向該方法。從而避免這個問題:
*/

function createCar2(sColor){
   
var car =new Object();
    car.color 
= sColor ;
    car.showColor 
= showColor ;

   
return car ;
}


function showColor(){
    alert(
this.color);
}


var oCar1 = createCar('red');
var oCar2 = createCar('yellow');

var oCar3 = createCar2('blue');
var oCar4 = createCar2('black');

/*
    注意這兩個物件(oCar3 和 oCar4 ) 呼叫showColor 屬性的方式,雖然美其名曰是“屬性”,其實還是方法!!!
    所以是 oCar3.showColor(); 而不是 oCar3.showColor ;
*/


oCar3.showColor();
oCar4.showColor();

/*
  在這段重寫的程式碼中,在函式 createCar2() 前定義了函式showColor(), 在 createCar2() 內部,賦予物件一個已經
  指向已經存在的 showColor() 函式的指標,從功能上講,這樣解決了重複建立物件的問題,但該函式看起來不像物件
  的方法。

  所有這些問題引起了開發者的定義建構函式的出現
*/


// 2. 建構函式方式
function Car(sColor){
   
this.color = sColor;
    
this.showColor =function(){
        alert(
this.color);
    }
;
}
var car1 =new Car('red');
car1.showColor();

/*
  你可能已經注意到第一個的差別了,在建構函式內部無建立物件,而是使用 this 關鍵字,使用 new 
  運算子呼叫建構函式,在執行第一行程式碼前先建立一個物件,只有用 this 才能訪問該物件。然後可以
  直接賦予 this 屬性,預設情況下是建構函式的返回值,(不必明確使用 return 運算子)。
  這種方式在管理函式方面與工廠方法一樣都存在相同的問題.
*/
// 3. 原型方式
function PCar(){
}


PCar.prototype.color 
="blue";
var pcar1 =new PCar();

/*
  呼叫 new Car()時,原型的所有屬性都被立即賦予要建立的物件,意味著所有的 PCar 例項存放的是指向
  showColor() 函式的指標,從語義看起來都屬於一個物件,因此解決了前面兩種方式存在的問題。此外使用
  該方法,還能使用 instanceof 運算子檢查給定變數指向的物件型別。因此下面的程式碼將輸出 true:
*/

alert(pcar1 
instanceof PCar);  // output "true"
/*
  這個方法看起來不錯,遺憾的是,它並不盡人意。
  1. 首先這個建構函式沒有引數。使用原型方式時,不能給建構函式傳遞引數初始化屬性值,因為 pcar1 和
      pcar2 的屬性都等於 "blue"
  2. 真正的問題出現在屬性指向的物件,而不是函式時,函式共享不會造成任何問題,但是物件卻是很少被多個
      例項共享的。
*/



// 4. 混合的建構函式/原型方式(推薦)
/*
  聯合使用建構函式和原型方式,就可像使用其他程式設計語言一樣建立物件,這種概念非常簡單,即用建構函式
  定義物件的所有非函式屬性,用原型方式定義物件的函式屬性(方法)。
*/


function hCar(sColor){
   
this.color = sColor;    
   
this.drivers =new Array('Mike','Sue');
}


hCar.prototype.showColor 
=function(){
    alert(
this.color);
}
var hcar1 =new hCar('y color');
var hcar2 =new hCar('r color');

hcar1.drivers.push('Matt');

alert(hcar1.drivers);  
// output "Mike,Sue,Matt"alert(hcar2.drivers);  // output "Mike,Sue"// 5. 動態原型方式 (推薦)/*
  對於習慣使用其他開發語言的開發者來說,使用混合建構函式/原型方式感覺不那麼和諧。批評建構函式/原型方式的人
  認為,在建構函式內找屬性,在外部找方法的做法不合理。所以他們設計了動態原型方式,以供更友好的編碼風格。

  動態原型方式的基本想法與混合建構函式/原型方式 相同,即在建構函式內定義非函式的屬性,而函式的屬性則利用
  原型屬性定義。唯一的區別是賦予物件方法的位置。下面是使用動態原型方法重寫的 Car 類:
*/


function DCar(sColor){
   
this.color = sColor;
   
this.drivers =new Array('Mike','Sue');
   
    
if(typeof DCar._initialized == 'undefined'){
       
        DCar.prototype.showColor 
=function(){
            alert(
this.color);
        }

    }


    DCar._initialized 
=true;
}
var dcar1 =new DCar('y dcar');
var dcar2 =new DCar('b dcar');

dcar1.showColor();
dcar2.showColor();

alert(DCar._initialized);    
// output "true"alert(dcar1._initialized);  // output "undefined"
</script>