1. 程式人生 > >面對對象的程序設計

面對對象的程序設計

是否 循環 fig 多個 討論 false 無法創建 name屬性 位置

面向對象(Object-Oriented, OO)的語言有一個標誌,那就是它們都有類的概念,而通過類可
以創建任意多個具有相同屬性和方法的對象。

一、理解對象:

第一種:基於Object對象

1 var person = new Object();
2 person.name = "Nicholas";
3 person.age = 29;
4 person.job = "Software Engineer";
5 person.sayName = function(){
6 alert(this.name);
7 };

第二種:對象字面量方式(比較清楚的查找對象包含的屬性及方法)

1 var person = {
2     name: "Nicholas",    
age: 29, 4 job: "Software Engineer", 5 sayName: function() { 6 alert(this.name); 7 } 8 };

二、對象屬性類型

ECMA-262 第 5 版在定義只有內部才用的特性(attribute)時,描述了屬性(property)的各種特征 。ECMAScript中有兩種屬性:數據屬性和訪問器屬性。

1、數據屬性:
數據屬性指包含一個數據值的位置,可在該位置讀取或寫入值,該屬性有4個供述其行為的特性: [[configurable]]:表示能否使用delete操作符刪除從而重新定義,或能否修改為訪問器屬性。默認為true; [[Enumberable]]:表示是否可通過for-in循環返回屬性。默認true; [[Writable]]:表示是否可修改屬性的值。默認true; [[Value]]:包含該屬性的數據值。讀取/寫入都是該值。默認為undefined;如上面實例對象person中定義了name屬性,其值為“Nicholas”,對該值的修改都反正在這個位置 要修改對象屬性的默認特征(默認都為true),可調用Object.defineProperty()方法,它接收三個參數:屬性所在對象,屬性名和一個描述符對象(必須是:configurable、enumberable、writable和value,可設置一個或多個值)。
1
var person = {}; 2 Object.defineProperty(person, "name", { 3 configurable: false, 4 value: "Nicholas" 5 }); 6 alert(person.name); //"Nicholas" 7 delete person.name; 8 alert(person.name); //"Nicholas"

把 configurable 設置為 false,表示不能從對象中刪除屬性。如果對這個屬性調用 delete,則在非嚴格模式下什麽也不會發生,而在嚴格模式下會導致錯誤。而且,一旦把屬性定義為不可配置的,就不能再把它變回可配置了。此時,再調用 Object.defineProperty()方法修改除 writable 之外的特性,都會導致錯誤.

在調用 Object.defineProperty()方法時,如果不指定, configurable、 enumerable 和
writable 特性的默認值都是 false。

2、訪問器屬性:

它主要包括一對getter和setter函數,在讀取訪問器屬性時,會調用getter返回有效值;寫入訪問器屬性時,調用setter,寫入新值;該屬性有以下4個特征: [[Configurable]]:是否可通過delete操作符刪除重新定義屬性; [[Numberable]]:是否可通過for-in循環查找該屬性; [[Get]]:讀取屬性時調用,默認:undefined; [[Set]]:寫入屬性時調用,默認:undefined; 訪問器屬性不能直接定義,必須使用defineProperty()來定義,如下:
 1 var book = {
 2     _year: 2004,
 3     edition: 1
 4 };
 5 Object.defineProperty(book, "year", {
 6     get: function() {
 7         return this._year;
 8     },
 9     set: function(newValue) {
10         if(newValue > 2004) {
11             this._year = newValue;
12             this.edition += newValue - 2004;
13         }
14     }
15 });
16 book.year = 2005;
17 alert(book.edition); //2

以上代碼創建了一個 book 對象,並給它定義兩個默認的屬性: _year 和 edition。 _year 前面的下劃線是一種常用的記號,用於表示只能通過對象方法訪問的屬性。而訪問器屬性 year 則包含一個getter 函數和一個 setter 函數。 getter 函數返回_year 的值, setter 函數通過計算來確定正確的版本。因此,把 year 屬性修改為 2005 會導致_year 變成 2005,而 edition 變為 2。這是使用訪問器屬性的常見方式,即設置一個屬性的值會導致其他屬性發生變化。

三、創建對象

雖然 Object 構造函數或對象字面量都可以用來創建單個對象,但這些方式有個明顯的缺點:使用同一個接口創建很多對象,會產生大量的重復代碼。為解決這個問題,人們開始使用工廠模式的一種變體。

1、工廠模式

工廠模式是軟件工程領域一種廣為人知的設計模式,這種模式抽象了創建具體對象的過程(本書後面還將討論其他設計模式及其在 JavaScript 中的實現)。考慮到在 ECMAScript 中無法創建類,開發人員就發明了一種函數,用函數來封裝以特定接口創建對象的細節,如下面的例子所示。

 1 function createPerson(name, age, job) {
 2             var o = new Object();
 3             o.name = name;
 4             o.age = age;
 5             o.job = job;
 6             o.sayName = function() {
 7                 alert(this.name);
 8             };
 9             return o;
10         }
11         var person1 = createPerson("Nicholas", 29, "Software Engineer");
12         var person2 = createPerson("Greg", 27, "Doctor");

工廠模式雖然解決了創建多個相似對象的問題,但卻沒有解決對象識別的問題(即怎樣知道一個對象的類型)。

2、構造函數模式

 1 function Person(name, age, job) {
 2     this.name = name;
 3     this.age = age;
 4     this.job = job;
 5     this.sayName = function() {
 6         alert(this.name);
 7     };
 8 }
 9 var person1 = new Person("Nicholas", 29, "Software Engineer");
10 var person2 = new Person("Greg", 27, "Doctor");

使用自定義的構造函數(與普通函數一樣,只是用它來創建對象),定義對象類型(如:Person)的屬性和方法。它與工廠方法區別在於:

  • 沒有顯式地創建對象
  • 直接將屬性和方法賦值給this對象;
  • 沒有return語句;

此外,要創建Person的實例,必須使用new關鍵字,以Person函數為構造函數,傳遞參數完成對象創建;實際創建經過以下4個過程:

  1. 創建一個對象
  2. 將函數的作用域賦給新對象(因此this指向這個新對象,如:person1)
  3. 執行構造函數的代碼
  4. 返回該對象

未完待續,後期再補

面對對象的程序設計