面向?qū)ο螅∣bject-Oriented郑兴,OO)的語言有一個(gè)標(biāo)志廊营,那就是它們都有類的概念,而通過類可以創(chuàng)建任意多個(gè)具有相同屬性和方法的對(duì)象欲间。ECMAScript中沒有類的概念贮懈,因此它對(duì)對(duì)象也與基于類的語言中的對(duì)象有所不同匀泊。
ECMA-262把對(duì)象定義為:“無序?qū)傩缘募希鋵傩钥梢园局刀淠恪?duì)象或者函數(shù)各聘。”這就相當(dāng)于說對(duì)象是一組沒有特定順序的值抡医。對(duì)象的每個(gè)屬性或方法都有一個(gè)名字躲因,每個(gè)名字都映射到一個(gè)值。忌傻〈舐觯可以不ECMAScript的對(duì)象想象成散列表:就是一組名值對(duì),其中值可以是數(shù)據(jù)或函數(shù)水孩。
理解對(duì)象
創(chuàng)建自定義對(duì)象:
方法一:創(chuàng)建一個(gè)Object實(shí)例
var person = new Object();
person.name ="Icey";
person.age = 25;
person.job = "Softerware Engineer";
person.sayName = function () {
alert(this.name);
}
方法二:對(duì)象字面量創(chuàng)建對(duì)象
var person = {
name:"Icey",
age:25,
job:"Softerware Engineer",
sayName:function () {
alert(this.name);
}
};
1. 屬性類型
ECMA-262定義這些特性是為了實(shí)現(xiàn)JavaScript引擎用的镰矿,因此在JavaScript中不能直接訪問它們。為了表示特性是內(nèi)部值俘种,該規(guī)范把它們放在兩對(duì)方括號(hào)中秤标,如[[Enumerable]]。
ECMAScript中有兩種屬性:數(shù)據(jù)屬性和訪問器屬性宙刘。
-
1.數(shù)據(jù)屬性
數(shù)據(jù)屬性包含一個(gè)數(shù)據(jù)值的位置苍姜。在這個(gè)位置可以讀取和寫入值。數(shù)據(jù)屬性有4個(gè)描述其行為的特性悬包。
- [[Configurable]]:表示能否通過delete刪除屬性從而重新定義屬性衙猪,能否修改屬性的特性,或者能否把屬性修改為訪問其屬性布近。這個(gè)特性的默認(rèn)值為true垫释。
- [[Enumerable]]:表示能否通過for-in循環(huán)返回屬性。直接在對(duì)象上定義的屬性吊输,默認(rèn)值為true饶号。
- [[Writable]]:表示能否修改屬性的值。直接在對(duì)象上定義的屬性季蚂,默認(rèn)值為true茫船。
- [[Value]]:包含這個(gè)屬性的數(shù)據(jù)值。讀取屬性的時(shí)候扭屁,從這個(gè)位置讀算谈,寫入屬性的時(shí)候,把值保存在這個(gè)位置料滥。這個(gè)特性的默認(rèn)值為undefined然眼。
像前面例子中那樣直接在對(duì)象上定義的屬性,它們的[[Configurable]]葵腹、[[Enumerable]]和[[Writable]]特性都設(shè)置為true,而[[Value]]特性被設(shè)置為指定的值高每。
var person = {
name : "Icey"
};
這里創(chuàng)建了一個(gè)名為name的屬性屿岂,為它指定的值是"Icey"。[[Value]]特性將被設(shè)置為"Icey",對(duì)這個(gè)值的任何修改都將反映到這個(gè)位置鲸匿。
要修改屬性默認(rèn)的特性爷怀,必須使用ECMAScript的Object.defineProperty()方法。這個(gè)方法接三個(gè)參數(shù):屬性所在的對(duì)象带欢、屬性的名字和一個(gè)描述符對(duì)象运授。描述符對(duì)象的屬性必須是:configurable、enumerable乔煞、writable和value吁朦。設(shè)置其中的一或多個(gè)值,可以修改對(duì)應(yīng)的特性值渡贾。
var person = {};
Object.defineProperty(person,"name",{
wriable:false,
value:"Icey"
});
alert(person.name); //"Icey"
person.name = "Root";
alert(person.name); //"Icey"
在非嚴(yán)格模式下逗宜,賦值操作將被忽略,在嚴(yán)格模式下剥啤,賦值操作將會(huì)拋出錯(cuò)誤锦溪。
var person = {};
Object.defineProperty(person,"name",{
configurable:false,
value:"Icey"
});
alert(person.name); //"Icey"
delete person.name;
alert(person.name); //"Icey"
一旦把屬性定義為不可配置的,就不能再把它變回可配置了府怯。
var person = {};
Object.defineProperty(person,"name",{
configurable:false,
value:"Icey"
});
//拋出錯(cuò)誤
Object.defineProperty(person,"name",{
configurable:true,
value:"Icey"
});
在調(diào)用Object.defineProperty()方法創(chuàng)建一個(gè)新的屬性時(shí)刻诊,如果不指定,configurable牺丙、enumerable和writable特性的默認(rèn)值都是false则涯。如果調(diào)用Object.defineProperty()方法只是修改一定義的屬性的特性,則無次限制冲簿。
-
2.訪問器屬性
訪問器屬性不包含數(shù)據(jù)值粟判;它們包含一對(duì)getter和setter函數(shù)(這兩個(gè)函數(shù)都不識(shí)必須的)。
在讀取訪問其屬性時(shí)峦剔,會(huì)調(diào)用getter函數(shù)档礁,這個(gè)函數(shù)負(fù)責(zé)返回有效的值;
在寫入訪問其屬性時(shí)吝沫,會(huì)調(diào)用setter函數(shù)并傳入新值呻澜,這個(gè)函數(shù)負(fù)責(zé)決定如何處理數(shù)據(jù)。
訪問器屬性有如下4個(gè)特性:
- [[Configurable]]:表示能否通過delete刪除屬性從而重新定義屬性惨险,能否修改屬性的特性羹幸,或者能否把屬性修改為訪問其屬性。這個(gè)特性的默認(rèn)值為true辫愉。
- [[Enumerable]]:表示能否通過for-in循環(huán)返回屬性栅受。直接在對(duì)象上定義的屬性,默認(rèn)值為true。
- [[Get]]:在讀取屬性時(shí)調(diào)用的函數(shù)屏镊,默認(rèn)值undefined依疼。
- [[Set]]:在讀取屬性時(shí)調(diào)用的函數(shù),默認(rèn)值undefined闸衫。
訪問器屬性不能直接定義涛贯,必須用Object.defineProperty()定義。
var book = {
_year:2017,
edition:1
};
Object.defineProperty(book,"year",{
get:function () {
return this._year;
},
set:function (newValue) {
if(newValue>2017){
this._year = newValue;
this.edition += newValue - 2017;
}
}
});
book.year = 2018;
alert(book.edition); //2
_year前面的下劃線是一種常用的記號(hào)蔚出,由于表示只能通過對(duì)象方法訪問的屬性。
把year修改成2018虫腋,會(huì)導(dǎo)致_year變成2018骄酗,edition變成2。使用訪問器屬性常見的方式悦冀,即設(shè)置一個(gè)屬性的值會(huì)導(dǎo)致其它屬性發(fā)生變化趋翻。
2. 定義多個(gè)屬性
Object.defineProperties()方法可以通過描述符一次定義多個(gè)屬性。這個(gè)方法接收兩個(gè)對(duì)象參數(shù):第一個(gè)對(duì)象是要添加和修改其屬性的對(duì)象盒蟆,第二個(gè)對(duì)象的屬性與第一個(gè)對(duì)象中要添加和修改的屬性一一對(duì)應(yīng)踏烙。
var book = {};
Object.defineProperties(book,{
_year:{
writable:true,
value:2004
},
edition:{
writable:true,
value:1
},
year:{
get:function () {
return this._year;
},
set:function (newValue) {
if(newValue>2017){
this._year = newValue;
this.edition += newValue - 2004;
}
}
}
});
book對(duì)象定義了兩個(gè)數(shù)據(jù)屬性和一個(gè)訪問器屬性。
3. 讀取屬性的特性
Object.getOwnPropertyDescriptor()方法可以取得給定屬性的描述符历等。這個(gè)方法接收兩個(gè)參數(shù):屬性所在的對(duì)象和要讀取其描述符的屬性名稱讨惩。返回值是一個(gè)對(duì)象。
var descriptor = Object.getOwnPropertyDescriptor(book,"_year");
alert(descriptor.value); //2004
alert(descriptor.configurable); //false
alert(typeof descriptor.get); //"undefined"
var descriptor = Object.getOwnPropertyDescriptor(book,"year");
alert(descriptor.value);//undefined
alert(descriptor.enumerable); //false
alert(typeof descriptor.get);//"function"