屬性型別
ES5定義了內部才用的特性時,描述了屬性的各種特征,ES5定義這些特征是為了實作 JavaScript 引擎用的,因此在 JavaScript 中不能直接訪問它們,為了表示特性時內部值,該規范把他們放在了兩對中括號中,例如 [[Enumerable]],
ECMAScript 中有兩種屬性:資料屬性和訪問器屬性,
資料屬性
資料屬性包含一個資料值的位置,在這個位置可以讀取和寫入值,資料屬性有4個描述其行為的特性:
| 特性 | 描述 | 默認值 |
|---|---|---|
| [[Configurable]](可配置的) | 表示能否通過 delete 洗掉屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性 | true |
| [[Enumerable]](可列舉的) | 表示能否通過 for-in 回圈回傳屬性 | true |
| [[Writable]](可寫入的) | 表示能否修改屬性的值 | true |
| [[Value]](屬性值) | 包含這個屬性的資料值,讀取屬性值的時候,從這個位置讀取 | undefined |
創建一個 屬性 為 name,屬性值 為 小明 的 student 物件
const student = {
name: '小明'
}
這里 name 的屬性值為 小明, 也就是說 name 的 [[Value]] 特性被設定成 '小明', 而對這個值的任何修改都將反映到這個位置上
要修改屬性默認的特性,只能使用 Object.defineProperty() 方法,
這個方法接收三個引數:屬性所在的物件,屬性名,和配置物件,
其中配置物件的屬性值為:
- configurable
- enumerable
- writable
- value
將物件 student 的屬性 name 的特性修改為不可洗掉的,可以通過 Object.defineProperty() 方法實作:
const student = {
name: '小明',
age: 22
}
Object.defineProperty(student, 'name', {
// 默認為true,當值為false時,該屬性不可以被 delete 洗掉
configurable: false
})
delete student.age
console.log(student) // { name: '小明' }
delete student.name // 嚴格模式下會拋出錯誤,非嚴格模式下會被忽略
console.log(student) // { name: '小明' }
將物件 student 的屬性 sex 配置為不可被列舉的代碼:
const student = {
name: '小明',
age: 22,
sex: '男'
}
for (const prop in student) {
console.log(prop) // name age sex
}
Object.defineProperty(student, 'sex', {
enumerable: false
})
for (const prop in student) {
console.log(prop) // name age
}
將物件 student 的屬性 name 改為只讀的:
const student = {
name: '小明'
}
Object.defineProperty(student, 'name', {
writable: false
})
student.name = '小紅' // 嚴格模式下會拋出錯誤,非嚴格模式下會被忽略
console.log(student.name) // 小明
訪問器屬性
訪問器屬性不包含資料值,它們包含一對 getter 和 setter 函式(它們不是必需的)
在讀取訪問器屬性時,會呼叫 getter 函式,這個函式負責回傳有效的值
在寫入訪問器屬性時,會呼叫 setter 函式并傳入新的值,這個函式負責決定如何處理資料
訪問器屬性有以下4個特性:
| 特性 | 描述 | 默認值 |
|---|---|---|
| [[Configurable]](可配置的) | 表示能否通過 delete 洗掉屬性從而重新定義屬性,能否修改屬性的特性,或者能否把屬性修改為訪問器屬性 | true |
| [[Enumerable]] | 表示能否通過 for-in 回圈回傳屬 | true |
| [[Get]] | 在讀取屬性時呼叫的函式 | undefined |
| [[Set]] | 在寫入屬性時呼叫的函式 | undefined |
訪問器屬性的前面時下劃線,表示只能通過物件方法訪問的屬性,下面代碼的訪問器屬性 birthday 中包含了一對 getter 和 setter 函式,
getter 函式回傳 _birthday 的值,setter 函式通過計算來確定正確的版本,因此,把 birthday 屬性修改為 '1999/04/22' 會導致 _birthday 變成 '1999/04/22',而 age 變為 22.
這是使用訪問器屬性的常見方式,即設定一個屬性的值會導致其他的屬性值發生變化,
const student = {
name: '小明',
age: 0,
_birthday: ''
}
Object.defineProperty(student, 'birthday', {
get: function(){ return this._birthday },
set: function(val){
this._birthday = val
this.age = new Date().getFullYear() - new Date(val).getFullYear()
}
})
student.birthday = '1999/04/22'
console.log(student) // {name: "小明", age: 22, _birthday: "1999/04/22"}
不一定非要同使指定 getter 和 setter, 只指定 getter 意味著屬性是不能寫入的,嘗試寫入屬性會被忽略,在嚴格模式下,嘗試寫入指定了 getter 函式的屬性會拋出錯誤, 類似地,只指定 setter 函式的屬性頁不能讀取,否則會拋出 undefine,在嚴格模式下會拋出錯誤,
定義多個屬性
由于為物件定義多個屬性的可能性很大,可以通過 Object.defineProperties() 方法來一次定義多個屬性,具體代碼如下:
const student = {}
Object.defineProperties(student, {
name: {
value: '小明'
// 以下被注釋的代碼不寫則屬性值默認為 false
// configurable: true,
// enumerable: true,
// writable: true
},
age: {
value: 0,
writable: true
},
_birthday: {
value: '',
writable: true
},
birthday: {
get: function() { return this._birthday },
set: function(val) {
this._birthday = val
this.age = new Date().getFullYear - new Date(val).getFullYear()
}
}
})
student.birthday = '1999/04/22'
console.log(student) // {name: "小明", age: NaN, _birthday: "1999/04/22"}
讀取屬性的特性
想要讀取屬性的特性,可以通過 Object.getOwnPropertyDescriptor() 方法,獲取 剛才以上的 student 屬性特性的代碼如下:
const descName = Object.getOwnPropertyDescriptor(student, 'name')
console.log(descName)
// {value: "小明", writable: false, enumerable: false, configurable: false}
const descAge = Object.getOwnPropertyDescriptor(student, 'age')
console.log(descAge)
// {value: 22, writable: true, enumerable: false, configurable: false}
const descBirth1 = Object.getOwnPropertyDescriptor(student, 'birthday')
console.log(descBirth1)
// {get: ?, set: ?, enumerable: false, configurable: false}
const descBirth2 = Object.getOwnPropertyDescriptor(student, '_birthday')
console.log(descBirth2)
// {value: "1999/04/22", writable: true, enumerable: false, configurable: false}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/253889.html
標籤:JavaScript
上一篇:jQuery使用hide()、toggle()函式實作相機品牌展示隱藏功能
下一篇:原始模式和工廠模式
