## 6.1 理解對象
**創建對象**
(1)創建自定義對象的最簡單方式就是創建一個Object的實例,然后給其添加屬性和方法:
~~~
var person = new Object();
person.name = 'tg';
person.age = 10;
person.say = function(){
console.log(this.name);
}
~~~
上面的例子創建了一個名為person的對象,并為它添加了兩個屬性(name、age)和一個方法(say())。
(2)對象字面量
~~~
var person = {
name: 'tg',
age: 10,
say: function(){
console.log(this.name);
}
}
~~~
這個person對象和上面例子是等價的。
### 6.1.1 屬性類型
ECMA-262第5版在定義只有**內部才用的特性**(attribute)時,描述了**屬性**(property)的各種特征。ECMA-262定義這些特性是為了實現JavaScript引擎用的,因此在JavaScript中**不能直接訪問**它們。
ECMAScript中有兩種屬性:**數據屬性**和**訪問權屬性**
**1. 數據屬性**
數據屬性包含一個數據值的位置,在這個位置可以讀取和寫入值。
數據屬性有4個描述特性的屬性:
| 屬性 | 描述 |
|---|---|
| [[Configurable]] | 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。比如直接在對象上定義的屬性,它們的這個特性默認值為true。|
| [[Enumerable]] | 表示能否通過for-in循環返回屬性。對于直接在對象上定義的值,默認為true。|
| [[Writable]] | 表示能否修改屬性的值,默認為true。|
| [[Value]] | 包含這個屬性的數據值。讀取屬性值時,從這個位置讀;寫入屬性值時,把新值保存在這個位置。默認值為undefined。|
要修改屬性默認的特性,必須使用ECMAScript 5的`Object.defineProperty()`方法,這個方法接收三個參數:屬性所在的對象、屬性的名字和一個描述符對象。其中,描述符對象的屬性必須是:`configurable、enumerable、writable和value`中的一個或多個。
~~~
var person = {};
Object.defineProperty(person, 'name', {
writable: false,
value: 'tg'
});
console.log(person.name); // "tg"
person.name = 'tg2';
console.log(person.name); // "tg"
~~~
在上面的例子中,我們將person對象中的名為name的屬性的writable設置為false,也就是不可修改,所以即使后面執行了person.name='tg2',最后person對象的name值依舊是原始值。
注意:在嚴格模式下,如果對一個不可修改的屬性執行賦值操作,會拋出錯誤;非嚴格模式下則忽略賦值操作。
一旦將configurable特性設置為false后,就不能再把它變回可配置的了,如果再修改除writable之外的特性,都會導致錯誤。類似規則也適用于configurable。
在調用Obejct.defineProperty()方法時,如果不指定,configurable、writable、enumerable特性的**默認值都為false**。
**2. 訪問器屬性**
訪問器屬性不包含數據值,它們包含一對getter和setter函數(非必需)。在讀取訪問器屬性時,會調用getter函數,返回有效的值;在寫入訪問器屬性時,會調用setter函數并傳入新值,它負責決定如何處理數據。
訪問器屬性:
| 屬性 | 描述 |
|---|---|
| [[Configurable]] | 表示能否通過delete刪除屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性。比如直接在對象上定義的屬性,它們的這個特性默認值為true。 |
| [[Enumerable]] | 表示能否通過for-in循環返回屬性。對于直接在對象上定義的值,默認為true。 |
| [[Get]] | 在讀取屬性時調用的函數,默認為undefined |
| [[Set]] | 在寫入屬性時調用的函數,默認為undefined |
訪問器屬性不能直接定義,也是要使用Object.defineProperty()方法來定義。
~~~
var book = {
_year:2004,
edition:1
};
Object.defineProperty(book,’year’,{
get:function(){
return this._year;
},
set:function(newValue){
if (newValue>2004) {
this._year = newValue;
this.edition += newValue-2004;
}
}
});
book.year = 2005;
alert(book.edition); //2
~~~
以上代碼創建了一個book對象,并給它定義了兩個默認屬性:`_year和edition`。前面的下劃線是一種常用的記號,用于表示**只能通過對象方法訪問的屬性**。在這個函數里,把year屬性修改為2005會導致`_year`變成2005,而`edition`變為2。這是使用訪問器屬性的常見方式,即**設置一個屬性的值會導致其他屬性發生變化。**
**3. 定義多個屬性**
ECMAScript 5提供的Object.defineProperties()方法可以通過描述符一次定義多個屬性,這個方法接收兩個對象參數,第一個對象是要添加和修改其屬性的對象,第二個對象的屬性與第一個對象要添加或修改的屬性一一對應。
~~~
var book = {};
Object.defineProperties(book,{
_year: {
value:2004
},
edition:{
value:1
},
year:{
get:function(){
return this._year;
},
set:function(newValue){
if (newValue>2004) {
this._year = newValue;
this.edition += newValue-2004;
}
}
}
});
~~~
**4. 讀取屬性的特性**
ECMAScript 5提供的`Object.getOwnPropertyDescriptor()`方法可以取得給定屬性的描述符,它接受兩個參數:屬性所在的對象和要讀取其描述符的屬性名稱,返回來的是一個對象,如果是訪問器屬性,這個對象的屬性有configurable、enumerable、get和set;如果是數據屬性,這個對象的屬性有configurable、enumerable、writable和value。
~~~
var descriptor = Object.getOwnpropertyDescriptor(book,’_year’);
alert(descriptor.value) //2005
alert(descriptor.configurable) //false
alert(descriptor.get) //undefined
console.log(descriptor.enumerable); // false
console.log(typeof descriptor.get); // "function"
~~~
這個方法只能用于實例屬性,要取得原型屬性的描述符,必須直接在原型對象上調用這個方法。
在JavaScript中,可以針對任何對象--包括DOM和BOM對象,使用Object.getOwnPropertyDescriptor()方法。
- 前言
- 第一章 JavaScript簡介
- 第三章 基本概念
- 3.1-3.3 語法、關鍵字和變量
- 3.4 數據類型
- 3.5-3.6 操作符、流控制語句(暫略)
- 3.7函數
- 第四章 變量的值、作用域與內存問題
- 第五章 引用類型
- 5.1 Object類型
- 5.2 Array類型
- 5.3 Date類型
- 5.4 基本包裝類型
- 5.5 單體內置對象
- 第六章 面向對象的程序設計
- 6.1 理解對象
- 6.2 創建對象
- 6.3 繼承
- 第七章 函數
- 7.1 函數概述
- 7.2 閉包
- 7.3 私有變量
- 第八章 BOM
- 8.1 window對象
- 8.2 location對象
- 8.3 navigator、screen與history對象
- 第九章 DOM
- 9.1 節點層次
- 9.2 DOM操作技術
- 9.3 DOM擴展
- 9.4 DOM2和DOM3
- 第十章 事件
- 10.1 事件流
- 10.2 事件處理程序
- 10.3 事件對象
- 10.4 事件類型
- 第十一章 JSON
- 11.1-11.2 語法與序列化選項
- 第十二章 正則表達式
- 12.1 創建正則表達式
- 12.2-12.3 模式匹配與RegExp對象
- 第十三章 Ajax
- 13.1 XMLHttpRequest對象
- 你不知道的JavaScript
- 一、作用域與閉包
- 1.1 作用域
- 1.2 詞法作用域
- 1.3 函數作用域與塊作用域
- 1.4 提升
- 1.5 作用域閉包
- 二、this與對象原型
- 2.1 關于this
- 2.2 全面解析this
- 2.3 對象
- 2.4 混合對象“類”
- 2.5 原型
- 2.6 行為委托
- 三、類型與語法
- 3.1 類型
- 3.2 值
- 3.3 原生函數