JavaScript 是一種物件導向的程式語言,但確不存在類別的概念,這跟我們以往在 Java、C++、C# 等語言上所學到的物件導向觀念有很大的不同,也是一般JavaScript 初學者所要適應與轉變的觀念。談 OOP 總離不開封裝、繼承與多型等基本觀念,而 JavaScript 在實作這三者時與Java、C++、C# 等語言也有著截然不同的作法,唯有先搞清楚 JavaScript 中原型式的物件導向觀念與作法,才能在使用 JavaScript 這門語言時游刃有餘。首先我們將透過如何在 JavaScript 中建立物件的幾種方式來展開 JavaScript OOP 之旅。
在 JavaScript 中要建立一個物件,非常簡單,不像Java、C++、C# 等語言要透過 Class 才有辦法建立一個物件。
第一種方法是透過所謂的實字符號模式(literal notation patterns) ,快速的建立一個物件,如下程式片段:
var dog = {}; //空物件
dog.name = “harry”;
dog.getName = function(){
return dog.name;
};
也可以這樣建立一個新物件:
var dog = {
name: “harry”,
getName: function(){
return this.name; //or return name
}
};
當我們只想為物件建立一個執行個體時,會使用此方式,此方式不適合於需建立多個相同物件模板的運用。
第二種方式是透過內建的建構式(constructor functions)來建立一個新的物件:
var dog = new Object();//空物件,但會自動從 Object.prototype 承屬性與方法
console.log(dog.constructor === Object)’ //true
dog.name = “harry”;
此種方式也只適用於想為物件建立一個執行個體時使用。
另外需注意的是: Object 可以接受一個參數,此時傳回的就不一定是 Object 如下例:
var obj = new Object(1);
console.log(o.constructor === Number);
//true
var obj = new Object(“harry”);
console.log(o.constructor === String);
//true
var obj = new Object(true”);
console.log(o.constructor === Boolean);
//true
所以在使用上時要別別小心,尤其是在動態建立物件的情況下,可能很容易得到不如預期的結果。
第三種方法是透過自訂建構式函式來建立新物件,透過這種方式建立物件,JavScript 引擎會在背後做一些事,如下例:
var Dog = function(name){
//使用物件實字自動建立一個空物件
// var this
= Object.create(Dog.prototype);
this.name =
name;
this.getName = function(){
return
this.name;
};
// return this; //隱式傳回 this 物件
};
var
dog = new Dog(“harry”); //雖然很像 Java與 c# 中透過類別建立物件的方式,但它並不是,它稱為函式建構子
dog.getName; //harry
這種建立物件的方式有一個缺點,就是你每建立一個新的物件,就會有一個新的屬性及方法被建立在記憶體中,對於物件的屬性來說是合理,因為每個物件的屬性值本來就會有所不同,但對於可重覆利用的方法來說,很明顯這是一種記憶體上的浪費,應該透過如下的程式片段來達成方法的共用:
var Dog = function(name){
this.name =
name;
};
Dog.prototype.getName = function(){
return
this.name;
};
這樣當透過自訂建構式函式建立二個以上的物件時,實際上只會在記憶體建立一份方法:
var dog1 = new Dog(“harry”);
dog1.getName; //harray
var dog2 = new Dog(“marry”);
dog2.getName; // marry
自訂建構式函式時,也可以透如下的方式定義屬性和方法
var Dog = function({
};
Dog.name = “harray”;
Dog.getName = function(){
return this.name;
};
但需注意的是,透過這種方式宣告的屬性與方法稱為靜態屬性與方法,有如下的特性:
console.log(Dog.name); //harry
console.log(typeof Dog. getName); //function
var o=new Dog ();
console.log(o.name); //undefined
console.log(typeof Dog. getName); //function
var o=new Dog ();
console.log(o.name); //undefined
console.log(typeof o. getName); //undefined
另外,關於自訂建構式函式需要注意的是,一定要使用 new 來建立物件,如果忘了使用 new 在建構式中的 this 就會指向全域物件,也就是在瀏覽器中, this 就指向 window
var dog = Dog();
console.log(typeof dog); // undefined 忘了new, 不會有物件this回傳, 變成全域
console.log(window.name); //全域變數
可以透過下列的技巧讓自訂建構式函式無論使用那一種方式,一定會回傳物件:
優點
|
缺點
|
|
實字物件建立方法
|
快速而簡潔的建立單一物件。
|
無法透過它去完成建立同一類型物件的多個實例。
|
內建建構式函式
|
可透過參數建立不同型別的物件
|
1.
無法透過它去完成建立同一類型物件的多個實例。
2.
當傳入不同參數會得到不同的預期結果。所以通常不建議採用此方法來建立新物件,可直接採用實字法。
|
自訂建構式函式
|
1.
可以建立同一類型物件的多個實例。
2.
可以建立靜態屬性與方法,使之成為工具類別,服務整個應用。
|
建立方式比較複雜,需了解不同建立方式間的區別。
|
在上面三種建立物件的方法時,有二個 keyword 出現,一個是 prototype 及 constructor,下一篇文章,我們將介紹這二個 keyword 讓我們向 JavaScript 式的 OOP 更接近一步。
參考文件:
沒有留言:
張貼留言