属性标志和属性描述符
属性标志
平时我们用的对象值,其实是一个属性的标志之一 value
,其他三个是:
writable
是否可写enumerable
是否可遍历configurable
是否可配置,表示属性是否可被删除,被修改。
使用常用对象字面量方式声明一个属性时,上面三个值默认都是 true
。
获取属性描述符
- 获取单个:
getOwnPropertyDescriptor(obj, propertyName)
- 获取所有:
getOwnPropertyDescriptors(obj)
注意:可获取Symbol属性
返回值如下:
var obj = {name: 'John'}
getOwnPropertyDescriptor(obj, 'name');
{
"value": "John",
"writable": true,
"enumerable": true,
"configurable": true
}
设置属性描述符
- 设置单个:
defineProperty(obj, propertyName, descriptor)
- 设置多个:
defineProperties(obj, {prop1: descriptor1, prop2: descriptor2})
注意:如果只设置value的话,其他属性描述符的值默认是 false
,而使用对象字面量等常规方式设置属性值,其他属性描述符默认是 true
。所以如果使用该方法设置属性,其他描述符的值需要设置指明,以防意外。
只读
设置 writable
为 false
即可。
注意:再次对属性赋值,严格模式下会抛错,非严格模式下忽略
不可枚举
设置 enumerable
为 false
。
注意:则 for in
, Object.keys
都无法获取到
不可配置
设置 configurable
为 false
。
注意:该配置用途是防止更改和删除,但是可以修改 value
属性的值,前提是它是可 writable
的,如果本身已不是可写的,之后也无法从不可写改成可 writable
状态。
// 实现一个常量
let user = {name: 'John'}
Object.defineProperty(user, 'name', {
configurable: false,
writable: false
})
// 无法修改描述符
强力克隆
for in
, Object.keys
无法遍历出 Symbol
属性。
- 使用
...
可以实现克隆Symbol
- 使用
Object.defineProperties({}, Object.getOwnPropertyDescriptor(obj))
密封对象
这些方法用的不是很多禁止添加新属性
Object.preventExtensions(obj)
,对应检测方法Object.isExtensible(obj)
禁止添加/删除属性
Object.seal(obj)
,相当于设置configurable: false
,对应检测方法Object.isSealed(obj)
禁止添加/删除/修改属性值
Object.freeze(obj)
,相当于configurable:false
writable: false
,对应检测方法Object.isFrozen(obj)
属性的getter和setter
前文描述的都是数据属性,这里将描述的是 访问器属性,本质是用于获取和设置值的函数。
Getter和Setter
对象字面量中,使用 get & set
来表示。
let obj = {
get name() {}, // 读取时使用
set name() {} // 设置时使用
}
访问器描述符
没有 value & writable
取而代之的时 get & set
,两者只能选其一,同时设置将报错。
let obj = {}
Object.defineProperty(obj, 'name', {
get() {
return ..
},
set(v) {
this.x = v
}
})