1. 程式人生 > 其它 >淺談JavaScript的面向物件程式設計(一)

淺談JavaScript的面向物件程式設計(一)

  面向物件的語言有一個標誌,他們都有類的概念,通過類可以建立多個具有相同屬性和方法的物件。但是JavaScript中沒有類的概念,因此JavaScript與其他的面嚮物件語言還是有一定區別的。JavaScript把物件定義為無序屬性的集合,其屬性可以包含基本值、物件或者函式。物件的每個屬性或者方法都有一個名字,而每個名字都對映到一個值。所有我把JavaScript的物件看成一組無序的鍵值對。

物件是什麼

  以前曾介紹過物件的建立,建立物件最簡單的方式就是建立Object物件的一個例項,再為他新增屬性和方法。

1 var obj = new Object();
2 obj.name="test";
3 obj.getName=function(){
4     return this.name;
5 }
6 console.log(obj.getName());

  上面的程式碼第一行建立了一個物件obj,第二行給obj添加了屬性name,第三行給obj添加了方法getName。通過getName方法能夠獲取obj屬性name的值。第六行輸出字串test。

1 var obj = {};
2 obj.name="test";
3 obj.getName=function(){
4     return this.name;
5 }
6 console.log(obj.getName());

  上面的程式碼通過字面量建立了物件obj。其他與通過Object建立的完全一樣。

物件的屬性

  JavaScript有兩種屬性:資料屬性和訪問器屬性。

  • 資料屬性

  資料屬性包含一個數據值的位置。在這個位置可以讀取和寫入值。資料屬性有4個描述其行為的特性。

  Configurable:表示能否通過delete關鍵字刪除屬性或者把屬性修改為訪問器屬性。configurable預設是true。

  Enumerable:表示能否通過for-in迴圈,預設值為true。

  Writable:表示能夠修改屬性的值,預設為true。

  Value:包含這個資料的屬性值。讀取屬性值時,從這個位置讀。寫入屬性值的時候,把新值儲存在這個位置。預設為undefined。

  對於像前面那樣定義物件,他的configurable、enumerable和writable預設都是true,value是指定給它的值。

1 var obj={
2     name:"test";
3 }

  這建立的物件obj擁有一個屬性,並設定value值為test。要修改預設屬性必須使用Object.defineProperty()方法。這個方法接收三個引數:屬性所在的物件、屬性的名字和描述符。描述符物件的屬性必須是configurable、enumerable、writable和value中的一個或者多個。

 1 var obj={
 2                 };
 3                 Object.defineProperty(obj,"name",{
 4                     configurable:true,
 5                     value:"hehe",
 6                     enumerable:true,
 7                     writable:false
 8                 });
 9                 obj.name="test";
10                 console.log(obj.name);//輸出hehe

  這個例子建立了一個屬性name,並設定wriable為false,也就是說name屬性的value將無法寫入。所在我在第九行修改name的值,並沒有效果。name的值依然為test。

  把configurable設定為false之後,該屬性就將無法通過delete刪除,同時也不能通過Object.defineProperty()方法設定除writable之後的值。在嚴格模式下,如果呼叫該方法將會報錯。

  當通過Object.defineProperty方法定義屬性的時候,configurable、enumerable和writable特性的預設值是false。所以,最好不要通過該方法定義屬性。

  • 訪問器屬性

訪問器屬性不包含value,但是包含一對getter和setter函式。在讀取訪問器屬性時,會呼叫getter函式。在寫入訪問器屬性時,會呼叫setter函式。訪問器屬性有以下四個特性:

  Configurable:表示能否通過delete關鍵字刪除屬性或者把屬性修改為訪問器屬性。configurable預設是true。

  Enumerable:表示能否通過for-in迴圈,預設值為true。

  get:在讀取屬性的時候呼叫的函式,預設值為undefined。

  set:在寫入屬性的值時呼叫的函式,預設是undefined。

 1 var person={"_name":"hehe","age":18}
 2                 Object.defineProperty(person,"name",{
 3                     get:function(){
 4                         return this._name;
 5                     },
 6                     set:function(str){
 7                         
 8                         if(this._name!="haha"){
 9                             this._name=str;
10                             this.age="19";
11                         }
12                     }
13                 });
14                 person.name="haha";
15                 console.log(person.name+":"+person.age);//haha:19

  上面的程式碼建立了一個物件person,並定義了兩個屬性_name和age。_name表示內部屬性,一般由物件本身去訪問。定義了屬性name,有get和set方法。不一定要同時定義get和set方法。只有get方法,則嘗試寫入屬性的時候報報錯。只有set方法,則獲取屬性的時候會報錯。通過Object的defineProperties能夠同時定義多個屬性。

 1 var obj={};
 2                 Object.defineProperties(obj,{
 3                     name:{
 4                         value:"hehe"
 5                     },
 6                     age:{
 7                         value:"18"
 8                     }
 9                 });
10                 console.log(obj.name+":"+obj.age);//hehe:18

  上面的程式碼,通過Object的defineProperties方法同時定義了兩個屬性name和age。該方法的第一個引數是物件,第二個引數是由需要定義的屬性組成的物件。

  • 讀取屬性的特性

  JavaScript提供了Object.getOwnPropertyDescriptor方法,可以獲取屬性的描述符。這個方法需要兩個引數:第一個引數是物件,第二個引數是描述符屬性的名稱。返回值是一個物件,如果是訪問器屬性則有configurable、enumerable、writable、get和set。如果是資料屬性,這個物件有屬性configurable、enumerable、writable和value。

 1 var obj={};
 2                 Object.defineProperties(obj,{
 3                     name:{
 4                         value:"hehe"
 5                     },
 6                     age:{
 7                         value:"18"
 8                     },
 9                     _sex:{
10                         value:"man"
11                     },
12                     sex:{
13                         get:function(){
14                             return this._sex;
15                         },
16                         set:function(str){
17                             this._sex=str;
18                         }
19                     }
20                 });
21                 var descriptor1=Object.getOwnPropertyDescriptor(obj,"name");
22                 var descriptor2=Object.getOwnPropertyDescriptor(obj,"sex");
23                 console.log(descriptor1.writable);//false
24                 console.log(descriptor2.get);//function
25                 console.log(obj.name+":"+obj.age+","+obj.sex);//hehe:18,man

  上面的程式碼,通過Object.getOwnPropertyDescriptor()方法獲取屬性的描述嗎,分別獲取了資料屬性以及訪問器屬性。