Object.defineProperty()
定义:Object.defineProperty(object, propName, descriptor)为对象定义新的属性,或者对某个属性进行修改,并将这个对象返回出来
object:对象 给谁加
propName:属性名 要添加的属性的名字,是一个字符串
descriptor:属性描述 要加的这个属性有什么特点
属性描述对象的6个属性:
value 属性的值
writable 属性值是否可以重写,默认为false
enumerable 属性值是否可枚举,默认为false
configurable 属性值是否可删除/是否可以再次修改特性,默认为false
set 目标属性设置值的方法
get 目标属性获取值的方法
1、descriptor的第一个属性:value 要加的属性值是什么,默认值:undefined
Object.defineProperty(user, 'name', { value: '小明' }) Object.defineProperty(user, 'isShow', { value: true }) Object.defineProperty(user, 'age', { value: 18 }) Object.defineProperty(user, 'sayHi', { value: function() { console.log('hi') } }) Object.defineProperty(user, 'hobby', { value: { a: '篮球', b: '足球' } }) console.log(user) // {name: '小明', isShow: true, age: 18, hobby: { a: '篮球', b: '足球' }, sayHi: ƒ}
2、descriptor的第二个属性:writable 属性是否可以被重新赋值,默认值:false
const user = {} Object.defineProperty(user, 'name', { value: '小明' }) user.name = '小小明' // 此时无法改变name的值 console.log(user) // {name: '小明'}
const user = {} Object.defineProperty(user, 'name', { value: '小明', writable: true // 默认值为false,当设置为true时可以重新赋值name }) user.name = '小小明' console.log(user) // {name: '小小明'}
3、descriptor的第三个属性:enumerable 是否可以被枚举,默认值:false
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男', enumerable: true }) Object.defineProperty(user, 'score', { value: 100, enumerable: false // 此时该属性不可以被遍历 }) const keys = Object.keys(user) console.log(keys) // ['name', 'age', 'gender']
要注意,不可枚举属性可以通过对象.获取,但是它是不可以被遍历的,并不是说不能通过对象去获取这个值了
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男' }) const keys = Object.keys(user) console.log(keys) // ['name', 'age'] for (let item in user) { console.log(item) // name age } console.log(user) // {name: '小明', age: 18, gender: '男'}
4、descriptor的第四个属性:configurable 是否可以被删除,是否可以在第一次定义后再重新定义,默认值:false
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男' }) delete user.gender // 删除无效 console.log(user) // {name: '小明', age: 18, gender: '男'}
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男' }) user.gender = '女' // 重新定义无效 console.log(user) // {name: '小明', age: 18, gender: '男'}
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男' }) // 使用Object.defineProperty()重新定义gender会报错 Object.defineProperty(user, 'gender', { value: '女' }) console.log(user) // Uncaught TypeError: Cannot redefine property: gender
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男', configurable: true }) delete user.gender // 删除有效 console.log(user) // {name: '小明', age: 18}
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男', configurable: true }) // 可以通过Object.defineProperty()重新定义gender Object.defineProperty(user, 'gender', { value: '女' }) console.log(user) // {name: '小明', age: 18, gender: '女'}
重新定义gender之后,configurable的值不设置为false即认为是继承了第一次设置的true,此时可以删除gender;一旦重新定义gender后设置了configurable为false,即不可以再进行设置,也不可以再删除
const user = { name: '小明', age: 18 } Object.defineProperty(user, 'gender', { value: '男', configurable: true }) // 可以通过Object.defineProperty()重新定义gender Object.defineProperty(user, 'gender', { value: '女', // configurable: false // 写了这句则不可以删除,否则值默认为第一次定义时的true }) delete user.gender // 若第二次定义gender时明确声明了configurable: false,此时不可以删除;若没有定义则认为继承了第一次定义时的true,此时可以删除 console.log(user) // {name: '小明', age: 18}
5、descriptor的第五个属性:存取器(set、get)
const user = { name: '小明' } let count = 12 const obj = Object.defineProperty(user, 'age', { get: function() { return count }, set: function(val) { count = val } }) console.log(user.age) // 12 user.age = 18 console.log(user.age) // 18
注意:
①set和get可以一起写,也可以写一个
②写了set或get后,不能设置value和writable属性了,否则会报错