Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。
语法 Object.defineProperty(obj, prop, descriptor)
- obj表示要定义的对象
- props,表示属性的名称
- descriptor,要修改的属性值
value
属性的值,可以是任意有效的js值
默认为 undefined
writable
当该属性为true时候,属性的value才能被修改
默认为 false
enumerable
当该属性为true时候,该属性才能出现在对象的枚举中,也就是for…in…,同时直接打印输出才能看到该属性
默认为 false
configurable
当且仅当该属性的 configurable 键值为 true 时,该属性的描述符才能够被改变,同时该属性也能从对应的对象上被删除
默认为 false
get
属性的 getter 函数,如果没有 getter,则为 undefined。当访问该属性时,会调用此函数。执行时不传入任何参数,但是会传入 this 对象(由于继承关系,这里的this并不一定是定义该属性的对象)。该函数的返回值会被用作属性的值
默认为 undefined
set
属性的 setter 函数,如果没有 setter,则为 undefined。当属性值被修改时,会调用此函数。该方法接受一个参数(也就是被赋予的新值),会传入赋值时的 this 对象
默认为 undefined
value,writable属性
由于writable默认为false,所以新添加的hobby属性不会被修改
// 直接在对象中定义的属性,是可以修改、枚举、和修改属性的
const obj = {
name: 'zz',
age: '18',
}
console.log('%c [ obj ]-22', 'font-size:13px; background:pink; color:#bf2c9f;', obj)
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: false,
// 需要配置configurable为true,否则无法修改hobby属性的配置
configurable: true,
})
obj.hobby = '------'
console.log('%c [ obj.hobby, writable false ]-31', 'font-size:13px; background:pink; color:#bf2c9f;', Object.keys(obj), obj.hobby)
修改代码为以下代码即可成功修改hobby的值为‘—’
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: true,
})
enumerable、configurable
上图成功修改hobby的值,但是通过Object.keys()无法读取hobby,这是因为enumerable默认为false,所以需要修改enumerable为true才能遍历,注意,下面为新的代码,通过Object.defineProperty修改enumerable属性
// 直接在对象中定义的属性,是可以修改、枚举、和修改属性的
const obj = {
name: 'zz',
age: '18',
}
console.log('%c [ obj ]-22', 'font-size:13px; background:pink; color:#bf2c9f;', obj)
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: true,
})
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: true,
// 配置enumerable为true
enumerable: true,
})
obj.hobby = '------'
console.log('%c [ obj.hobby, writable false ]-31', 'font-size:13px; background:pink; color:#bf2c9f;', Object.keys(obj), obj.hobby)
出现以上错误是因为,使用Object.defineProperty时候,configurable的值默认为false,所以是无法再次重新定义hobby属性
所以需要修改初次定义hobby属性时候,将configurable设置为true
// 直接在对象中定义的属性,是可以修改、枚举、和修改属性的
const obj = {
name: 'zz',
age: '18',
}
console.log('%c [ obj ]-22', 'font-size:13px; background:pink; color:#bf2c9f;', obj)
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: true,
// configurable设置为true,表示可以再次进行定义hobby属性
configurable: true,
})
// 添加属性
Object.defineProperty(obj, 'hobby', {
value: 'singer',
// writable为true才能被修改
writable: true,
// 配置enumerable为true
enumerable: true,
})
obj.hobby = '------'
console.log('%c [ obj.hobby, writable false ]-31', 'font-size:13px; background:pink; color:#bf2c9f;', Object.keys(obj), obj.hobby)
get、set
我们都知道,vue2的双向绑定原理就是基于Object.defineProperty的setter以及getter,通过一个例子了解该过程
以下例子中,通过定义一个变量hobby,然后给obj添加get以及set函数,每次获取obj.hobby时候,将hobby的值进行返回,每次设置obj.hobby时候,将该值赋值给hobby变量即可
// 直接在对象中定义的属性,是可以修改、枚举、和修改属性的
const obj = {
name: 'zz',
age: '18',
}
console.log('%c [ obj ]-22', 'font-size:13px; background:pink; color:#bf2c9f;', obj)
let hobby = 'singer'
obj.hobby = hobby
// 为height属性添加get方法
Object.defineProperty(obj, 'hobby', {
get: () => {
console.log('%c [ get singer ]-46', 'font-size:13px; background:pink; color:#bf2c9f;', )
return hobby
},
set: (value) => {
console.log('%c [ set singer ]-46', 'font-size:13px; background:pink; color:#bf2c9f;', )
hobby = value
}
})
console.log('%c [ obj.hobby ]-48', 'font-size:13px; background:pink; color:#bf2c9f;', obj, obj.hobby)
obj.hobby = '---'
console.log('%c [ obj.hobby ]-48', 'font-size:13px; background:pink; color:#bf2c9f;', obj, obj.hobby)