属性标志和属性描述符
属性标志
平时我们用的对象值,其实是一个属性的标志之一 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:falsewritable: 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}})
