Object.defineProperty
Object.defineProperty
方法可以定义(或修改)一个对象的属性, 并返回这个对象。该方法接受三个参数,分别是要操作的对象、要操作的属性名称、要操作的属性描述符。属性描述符有两种形式,分别是数据描述符和存取描述符,这两种形式只能二选一。
var obj = {}
//数据描述符
Object.defineProperty(obj, "a", {
value : 1,//可选,默认undefined ,可以是任何数据类型
writable : false,//可选,默认false,该属性的value是否能被赋值运算符改变
configurable : true,//可选,默认为false 该属性描述符是否可配置
enumerable : false//可选,默认false 该属性是否在被遍历时显示
})
//存取描述符
Object.defineProperty(obj, "a", {
get : ()=>{},//可选,默认undefined,必须是函数类型数据
set : ()=>{},//可选,默认undefined,必须是函数类型数据
configurable : false,//同数据描述符
enumerable : false//同数据描述符
})
属性描述符中的参数都是可选的。
如果属性描述符中省略某些字段,Object.defineProperty方法
将自动将其设置为默认值。
如果属性描述符中value,writable,get 和 set 全都没有,则该属性描述符将被认为是数据描述符。
如果属性描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
使用赋值操作添加属性在被遍历时会显示,属性的值可以被改变和删除。
使用 Object.defineProperty()
通过额外参数实现更加精确地操作和控制对象的属性。
在ES6中,由于Symbol类型的特殊性,用Symbol类型的值来做对象的key与常规的定义或修改不同,而
Object.defineProperty
是定义key为Symbol的属性的方法之一。
configurable
属性设置为false,表示该属性描述符是不可配置的,不能在数据和访问器属性类型之间切换。当试图改变不可配置的属性描述符中的属性时会抛出TypeError
(例外:要修改属性的当前值与新值相同)。
writable
属性设置为false
,表示value属性不可被赋值。当试图写入value属性时不会发生改变,也不会引发错误。
注意以下情况
writable:
false,
configurable:
false
属性不可改变(抛出TypeError
)
writable
:false,configurable:
true
value可通过Object.defineProperty方法改变,不能通过赋值改变(
不会引发错误)
writable
:true,configurable:
false
value可通过Object.defineProperty方法和赋值
改变,writable可单向改为fasle,其他
属性不可改变(抛出TypeError
)
writable
:true,configurable:
true
属性可改变。
getter 和 setter
Object.defineProperty(obj, "a", {
get : ()=>{
if(this.a === undefined){
this.a = 1
}
return this.a
},
set : (value)=>{
this.a = value + 1
},
configurable : false,
enumerable : false
})
console.log(obj.a) //1
obj.a = 2;
console.log(obj.a) //3
当访问该属性时,getter方法会被执行且没有参数传入,但是会传入this
对象(由于继承关系,这里的this
并不一定是定义该属性的对象)。
当属性值修改时,setter
方法会被执行并接受唯一参数,即该属性修改所传入的数据。