在 JavaScript 中,每個對象都是基于另一個對象創(chuàng)建的,也叫做對象的原型。所有對象都是通過其原型對象創(chuàng)建出來的。
不同的對象都有各自的屬性,ECMAScript 中有兩種類型的屬性:數(shù)據(jù)屬性和訪問器屬性。
數(shù)據(jù)屬性,就是最常見的有實實在在的值的屬性,訪問器屬性則是那些通過 getter 或 setter 函數(shù)進行訪問和賦值的屬性。對于這兩種屬性,都有描述各自行為的特性。首先來看數(shù)據(jù)屬性。
數(shù)據(jù)屬性
數(shù)據(jù)屬性有以下幾個描述其行為的特性:
-
[[Configurable]]:此描述符表示是否能夠刪除該屬性,默認為true -
[[Enumerable]]:此描述符表示該屬性是否可以通過for-in循環(huán)枚舉,默認為true -
[[Writable]]:此描述符表示該屬性是否可寫,默認為true -
[[Value]]:此描述符專門用來保存該屬性的值,讀取屬性時,從這個位置讀取,寫入屬性時(如果該屬性可寫的情況下),就寫入在這個位置。該描述符的默認值為undefined。
訪問器屬性
訪問器屬性不包含具體的屬性值,其包含了一對 getter 和 setter 函數(shù)(非必須),在讀取屬性值時,將調(diào)用 getter 函數(shù),將此函數(shù)的返回值作為讀取的值。在設置屬性時,將調(diào)用 setter 函數(shù),在該函數(shù)中完成對屬性值的設置。
訪問器屬性有以下幾個描述其行為的特性:
-
[[Configurable]]:同上 -
[[Enumerable]]:同上 -
[[Get]]:讀取屬性時調(diào)用的函數(shù),默認值為undefined -
[[Set]]:設置屬性時調(diào)用的函數(shù),默認值為undefined
訪問器屬性不能直接定義,必須通過 Object.defineProperty() 來進行定義。
Object.defineProperty() 方法
該方法用來對屬性進行配置,包括數(shù)據(jù)屬性和訪問器屬性。該函數(shù)接受三個參數(shù):
- 屬性所在的對象
- 屬性名
- 屬性描述符對象
調(diào)用該方法返回被定義后的對象。
1.定義數(shù)據(jù)屬性
let ball = {name:"basketball",brand:"NIKE"};
Object.defineProperty(ball,"name",{
writable:false
}); //{name:"basketball",brand:"NIKE"}
ball.name = "pingpang";
ball.name //"basketball";
2.定義訪問器屬性
let ball = {}
Object.defineProperty(ball,"name",{
get:function(){
return this._name
},
set:function(name){
this._name = name
}
})
ball.name //undefined
ball.name = "籃球"
ball.name //"籃球"
ball._name //"籃球"
ball._name = "足球"
ball.name //"籃球"
在 getter 函數(shù)中,我們訪問 name 屬性時返回當前對象的 _name 屬性,在 setter 函數(shù)中,我們設置 name 的值時會設置設置該對象的 _name 屬性,也就是 name 屬性的值始終依賴于 _name 屬性的值,而當我們修改 _name 屬性的值后,獲取到的 name 屬性的值也相應變化了。
關于 [[Configurable]] 描述符
一旦將 [[Configurable]] 設置為 false 后,該屬性就變成了“不可配置”狀態(tài),此時,除了對 [[Writable]] 描述符進行配置外,進行其他的配置都會報錯。
let ball = {}
Object.defineProperty(ball,"name",{
configurable:false,
value:"籃球"
})
// 再次配置
Object.defineProperty(ball,"name",{
configurable:true,
})
此時會產(chǎn)生錯誤:
VM3119:1 Uncaught TypeError: Cannot redefine property: name
但是我們?nèi)匀豢梢詫?[[Writable]] 描述符進行配置:
Object.defineProperty(ball,"name",{
writable:false,
})
ball.name = "足球"
ball.name //"籃球"
定義多個屬性
ES5 還提供了定義多個屬性的方法:Object.defineProperties(),該方法接受兩個參數(shù),第一個參數(shù)是配置屬性的對象,第二個參數(shù)是一個針對待配置屬性的描述字典:
let ball = {}
Object.defineProperties(ball,{
name:{
writable:false
},
brand:{
configurable:false
}
})
獲取屬性特性
通過 Object.getOwnPropertyDescriptor() 方法,可以獲取對象的屬性的描述符。該方法接受兩個參數(shù):屬性所在的對象和屬性名。
let ball = {}
Object.defineProperties(ball,{
name:{
writable:false
},
brand:{
configurable:false
}
})
Object.getOwnPropertyDescriptor(ball,"name") //{value: undefined, writable: false, enumerable: false, configurable: false}
另外,還有一個 Object.getOwnPropertyDescriptors()方法,可以獲取對象上所有的屬性特性,該方法只接受一個對象作為參數(shù),返回該對象所有的屬性描述符:
Object.getOwnPropertyDescriptors(ball)
返回值:
{
brand: {value: undefined, writable: false, enumerable: false, configurable: false},
name: {value: undefined, writable: false, enumerable: false, configurable: false}
}
完。