定义:
Object.defineProperty() 静态方法会直接在一个对象上定义一个新属性,或修改其现有属性,并返回此对象。
语法:
Syntax:
Object.defineProperty(obj, prop, descriptor)
参数:
一共接受三个参数 obj, prop, descriptor;
obj: 要定义属性的对象prop: 一个字符串或Symbol,指定了要定义或修改的属性键。desc: 配置项,一般是一个对象,有6个配置控制属性- value: 当前值, 默认:undefined;
- get: 读取时内部调用的函数, 默认:undefined;
- set: 写入时内部调用的函数, 默认:undefined;
- writable: 是否可以重写, 默认:false;
- enumerable: 是否可以被枚举,默认:false;
- configurable: 是否可以再次修改配置项,以及可否删除,默认:false;
desc6个配置项,组成了两类描述符:- 类1:数据描述符
- 组成:
- value
- writable
- enumerable
- configurable
- 组成:
- 类2:存取属性描述符(也叫 访问器描述符)
- 组成:
- get
- set
- enumerable
- configurable
- 组成:
- 类1:数据描述符
返回值:
传入函数的对象,其指定的属性已被添加或修改;
描述符详细介绍:
数据属性描述符:
-
[[configurable]]:表示属性是否可以通过delete删除,是否可以修改特性,是否可以将它修改为存取属性- (1)当我们直接在一个对象上定义某个属性时,它的默认值是true
- (2)而当我们通过属性描述符进行定义属性时,它的默认值是false
-
[[enumerable]]:表示属性是否可以通过for-in或者Object.keys返回属性- (1)当我们直接在一个对象上定义某个属性时,他的默认值是true
- (2)而当我们通过属性描述符进行定义属性时,他的默认值是false
-
[[writable]]:表示是否可以修改属性- (1)当我们直接在一个对象上定义某个属性时,他的默认值是true
- (2)而当我们通过属性描述符进行定义属性时,他的默认值是false
-
[[value]]:属性的value值,当读取属性时会返回value,修改属性时会修改value- (1)默认情况下value是undefined
存取属性描述符:
-
[[configurable]]:表示属性是否可以通过delete删除,是否可以修改特性,是否可以将它修改为存取属性- (1)当我们直接在一个对象上定义某个属性时,它的默认值是true
- (2)而当我们通过属性描述符进行定义属性时,它的默认值是false
-
[[enumerable]]:表示属性是否可以通过for-in或者Object.keys返回属性- (1)当我们直接在一个对象上定义某个属性时,他的默认值是true
- (2)而当我们通过属性描述符进行定义属性时,他的默认值是false
-
[[get]]:获取属性时执行的函数,默认为 undefined -
[[set]]:设置或者修改属性值时执行的函数,默认为 undefined
属性描述符的冲突
[[value]] 、[[writable]] 和 [[get]]、[[set]] 这两对不能同时出现;
Demo:
// Demo1: value
let Person = {}
Object.defineProperty(Person, 'name', { value: 'Jack' })
console.log('- Person.name ->: ',Person.name)
console.log('- Object.getOwnPropertyDescriptors(Person) ->: ', Object.getOwnPropertyDescriptors(Person))
Person.name = 'Leo'
console.log('- Person.name ->: ',Person.name) // Jack; 因为默认 wriable: false;
console.log('- Object.assign({}, Person) ->', Object.assign({}, Person)) // {}; 因为默认 enumerable: false;
console.log('- {...Person} ->: ',{...Person}) // {}; 因为默认 enumerable: false;
delete Person.name
console.log('- Person.name ->: ',Person.name) // Jack; delete 未生效;因为默认 configurable: false;
Object.defineProperty(Person, 'name', { value: 'Leo' })
console.log('- Person.name ->: ',Person.name) // TypeError: Cannot redefine property: name; 因为默认 configurable: false;
// Demo2: writable
let Person = {}
Object.defineProperty(Person, 'name', { value: 'Jack', writable: true })
Person.name = 'Leo'
console.log('- Person.name ->: ',Person.name) // Leo; 因为定义 Person.name 属性可以被重写(writeable: true);
// Demo3: enumerable
let Person = {}
Object.defineProperty(Person, 'name', { value: 'Jack', enumerable: true })
console.log('- {...Person} ->: ',{...Person}) // { name: 'Jack' }; 因为定义了 Person.name 属性可以被枚举(enumerable: true);
Object.defineProperty(Person, 'age', { value: 20, enumerable: false })
console.log('- {...Person} ->: ',{...Person}) // { name: 'Jack' }; 因为定义了 Person.age 属性不可以被枚举;
Object.defineProperty(Person, 'sex', { value: '男', enumerable: true })
console.log('- {...Person} ->: ',{...Person}) // { name: 'Jack', sex: '男' }; 因为定义了 Person.sex 属性可以被枚举(enumerable: true);
// Demo4: configurable
let Person = {}
Object.defineProperty(Person, 'name', { value: 'Jack', configurable: true })
console.log('- Person.name ->: ',Person.name) // Jack
Object.defineProperty(Person, 'name', { value: 'Leo' })
console.log('- Person.name ->: ',Person.name) // Leo; 因为默认设置了 configurable: true; 属性可以被重新定义;
delete Person.name
console.log('- Person.name ->: ',Person.name) // undefined; 因为默认设置了 configurable: true; 属性可以被删除;
// Demo5: getter setter
let Person = {}
Object.defineProperty(Person, 'name', {
value: 'Jack',
get () {},
enumerable: false,
configurable: false
})
console.log('- Person.name ->: ',Person.name)
// TypeError: Invalid property descriptor. Cannot both specify accessors and a value or writable attribute;
// 因为 [[value]] 、[[writable]] 和 [[get]]、[[set]] 这两对不能同时出现
// Demo6: getter setter
let Person = {}
Object.defineProperty(Person, 'name', {
get () {},
set () {},
enumerable: false,
configurable: false
})
console.log('- Person.name ->: ',Person.name) // undefined; 因为 get 没有设置返回值;
Person.name = 'Leo'
console.log('- Person.name ->: ',Person.name) // undefind; 因为 set 没有设置数据操作, get 没有设置返回值;
// Demo7: getter setter
let Person = {}
let nameValue = 'Jack'
Object.defineProperty(Person, 'name', {
get () {
return nameValue
},
set (newValue) {
nameValue = newValue
},
enumerable: false,
configurable: false
})
console.log('- Person.name ->: ',Person.name) // Jack; 因为 get 有返回值 nameValue;
Person.name = 'Leo'
console.log('- Person.name ->: ',Person.name) // Leo; 因为 set 对nameValue做了赋值,get 返回被赋值的 nameValue;