定義對象
兩種方式定義對象
let person = new Object()
obj.name = '蛙人'
obj.age = 23
obj.sex = 'male'
obj.getAge = function() {
return this.age
}
上面的例子創(chuàng)建了一個person對象實例,并為它添加了屬性及方法,在早期js開發(fā)人員經常使用這種方式,但是現(xiàn)在對象字面量成了首先方式,看一下字面量定義對象。
let person = {
name: '蛙人',
age: 23,
sex: 'male',
getAge() {
return this.age
}
}
可以看到上面這種使用字面量的方式定義對象更加簡潔明了,字面量的方式跟第一種定義方式是一樣的。
屬性類型
在說數據屬性時,咱們先來講一下js里的內部屬性, 在Es5版本中,在定義只有內部才用的特性attribute時,描述了屬性property的各種
特征, 定義這些特性是為了實現(xiàn)js引擎用的,因此在js里無法訪問內部屬性,內部屬性是兩個中括號括起來的例如 [[Enumerable]]。
數據屬性
數據屬性包含一個數據值的位置,在這個位置可以進行讀取和寫入值,那么這就是數據屬性描述對象。
-
[[Configuralbe]]: 表示是否可以delete刪除該屬性,是否能在對象上定義其它屬性,是否能修改屬性值,默認返回true。 -
[[Enumerable]]:表示是否可以枚舉該屬性for in, 默認返回true。 -
[[Writeable]]: 表示是否可以讀寫改屬性,默認返回true。 -
[[Value]]: 表示屬性值的位置,每次讀取屬性的時,從這個[[Value]]內部屬性返回值,寫入屬性值的時候,把值保存在這個位置,默認返回undefined,這也就是我們所讀取對象上不存在的屬性時,返回undefined的原因。
理論講完了,那么直接上代碼一把梭
[[Value]]
let person = {
name: '蛙人'
}
上面example中定義屬性name,為它的值默認 “蛙人” 也就是說,在內部屬性 [[Value]] 中保存了該值, 從這點我們明白,只要是對象中修改或寫入值,都會觸發(fā)內部屬性 [[Value]]。
修改屬性描述對象
如果要修改數據屬性的描述對象,使用Es5中Object.defineProperty()方法,這個方法接收三個參數,目標對象、要訪問的屬性、屬性的描述對象,描述對象必須是: configurable、enumerable,writeable、value, 設置其中一或多屬性,可以修改對應的描述屬性值。
let person = {}
Object.defineProperty(person, 'name', {
writeable: false, // 不能寫入
value: '你沒有permission'
})
console.log(person.name) // 你沒有permission
person.name = "蛙人"
console.log(person.name) // 你沒有permission
在上面example中,我們設置了person對象描述對象為只讀不可寫,又為它設置了value屬性,所以不管它怎么讀取都返回你沒有permission,怎么寫都不可以,需要注意的是上面代碼在嚴格模式下會拋出錯誤,在非嚴格模式下賦值操作則會忽略, 而且更為重要的一點,Object.defineProperty第三個參數必須寫,不然code報錯
訪問器屬性
數據訪問器屬性不包含數據值, 他們包含一對 getter和setter函數 (這兩個函數不是必需的 可選)。
在讀取訪問器屬性時,會調用getter函數,在寫入訪問器屬性時,會調用setter函數,函數接收一個參數這個參數就是寫入的值。
-
[[get]]:在讀取屬性時調用的函數,默認返回undefined -
[[set]]:在寫入屬性時調用的函數,默認返回undefined
訪問器屬性不能直接定義,使用Object.defineProperty(),請看下面 example
let person = {
_age: 23,
name: '蛙人'
}
Object.defineProperty(person, "age", {
get() {
return this._age
},
set(val) {
this._age = val
}
})
person.age = 24
上面example中,寫入age屬性就會觸發(fā)訪問器對象里的set函數,從而重新賦值,然后觸發(fā)get方法,返回該屬性值,上面使用了_age這種定義方式表示為常用的mark,表示只能通過對象方法訪問的屬性, 不要直接寫在get函數返回里返回自身 如:this.age = xxx 這樣會造成堆棧溢出
定義多個描述屬性
Es5版本中還有一個Api方法是定義多個對象寫入描述屬性, 該方法接收2個參數,目標對象、屬性值,請看下列example
let person = {}
Object.defineProperties(person, {
_age: {
value: 23
},
name: {
value: "蛙人"
},
age:{
get() {
return this._age
},
set(val) {
this._age = val;
}
}
})
上面example與 上一個example都是同樣的代碼效果,只不過定義方式不同,該方法不經常使用,大家知道就好。
獲取對象的描述屬性
Es5版本中定義了一個Api方法可以查看當前對象的描述屬性,Object.getOwnPropertyDescriptor(), 該方法接收2個參數,目標對象、屬性值。
let person = {
age: 23
}
let descriptor = Object.getOwnPropertyDescriptor(person, "age")
console.log(descriptor.writable) // true
console.log(descriptor) // {"value":23,"writable":true,"enumerable":true,"configurable":true}
上面example中可以清楚的看見當前的對象屬性的描述對象,這樣在出現(xiàn)bug的時候,我們也可以查看當前的描述屬性是否可以更改,快速定位bug,在js中可以針對任何對象使用Object.getOwnPropertyDescriptor(), 包括BOM和DOM對象,兼容IE9 +、Firefox4+、Safari5+、Opera12+、Chrome。
<b>如果該文章對你有幫助,請點個贊吧</b>