在 JavaScript 中,每个对象都是基于另一个对象创建的,也叫做对象的原型。所有对象都是通过其原型对象创建出来的。
不同的对象都有各自的属性,ECMAScript 中有两种类型的属性:数据属性和访问器属性。
数据属性,就是最常见的有实实在在的值的属性,访问器属性则是那些通过 getter
或 setter
函数进行访问和赋值的属性。对于这两种属性,都有描述各自行为的特性。首先来看数据属性。
数据属性
数据属性有以下几个描述其行为的特性:
-
[[Configurable]]
:此描述符表示是否能够删除该属性,默认为true
-
[[Enumerable]]
:此描述符表示该属性是否可以通过for-in
循环枚举,默认为true
-
[[Writable]]
:此描述符表示该属性是否可写,默认为true
-
[[Value]]
:此描述符专门用来保存该属性的值,读取属性时,从这个位置读取,写入属性时(如果该属性可写的情况下),就写入在这个位置。该描述符的默认值为undefined
。
访问器属性
访问器属性不包含具体的属性值,其包含了一对 getter
和 setter
函数(非必须),在读取属性值时,将调用 getter
函数,将此函数的返回值作为读取的值。在设置属性时,将调用 setter
函数,在该函数中完成对属性值的设置。
访问器属性有以下几个描述其行为的特性:
-
[[Configurable]]
:同上 -
[[Enumerable]]
:同上 -
[[Get]]
:读取属性时调用的函数,默认值为undefined
-
[[Set]]
:设置属性时调用的函数,默认值为undefined
访问器属性不能直接定义,必须通过 Object.defineProperty()
来进行定义。
Object.defineProperty() 方法
该方法用来对属性进行配置,包括数据属性和访问器属性。该函数接受三个参数:
- 属性所在的对象
- 属性名
- 属性描述符对象
调用该方法返回被定义后的对象。
1.定义数据属性
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
函数中,我们访问 name
属性时返回当前对象的 _name
属性,在 setter
函数中,我们设置 name
的值时会设置设置该对象的 _name
属性,也就是 name
属性的值始终依赖于 _name
属性的值,而当我们修改 _name
属性的值后,获取到的 name
属性的值也相应变化了。
关于 [[Configurable]]
描述符
一旦将 [[Configurable]]
设置为 false
后,该属性就变成了“不可配置”状态,此时,除了对 [[Writable]]
描述符进行配置外,进行其他的配置都会报错。
let ball = {}
Object.defineProperty(ball,"name",{
configurable:false,
value:"篮球"
})
// 再次配置
Object.defineProperty(ball,"name",{
configurable:true,
})
此时会产生错误:
VM3119:1 Uncaught TypeError: Cannot redefine property: name
但是我们仍然可以对 [[Writable]]
描述符进行配置:
Object.defineProperty(ball,"name",{
writable:false,
})
ball.name = "足球"
ball.name //"篮球"
定义多个属性
ES5 还提供了定义多个属性的方法:Object.defineProperties()
,该方法接受两个参数,第一个参数是配置属性的对象,第二个参数是一个针对待配置属性的描述字典:
let ball = {}
Object.defineProperties(ball,{
name:{
writable:false
},
brand:{
configurable:false
}
})
获取属性特性
通过 Object.getOwnPropertyDescriptor()
方法,可以获取对象的属性的描述符。该方法接受两个参数:属性所在的对象和属性名。
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()
方法,可以获取对象上所有的属性特性,该方法只接受一个对象作为参数,返回该对象所有的属性描述符:
Object.getOwnPropertyDescriptors(ball)
返回值:
{
brand: {value: undefined, writable: false, enumerable: false, configurable: false},
name: {value: undefined, writable: false, enumerable: false, configurable: false}
}
完。