1、概述:
JavaScript 提供了一个内部[数据结构],用来描述对象的属性,控制它的行为,比如该属性是否可写、可遍历等等。这个内部数据结构称为“属性描述对象”(attributes object)。每个属性都有自己对应的属性描述对象,保存该属性的一些元信息
2、属性的元信息
{
configurable:true,
writable:true,
enumerable:true,
value:'',
get(){
},
set(){
}
}
2.1 value属性
- configurable或writable其中一个为true时,才能修改成功
let proto = {
foo:'foo',
foo1:'foo1',
}
Object.defineProperty(proto,'foo',{
configurable:false,
writable:false,
enumerable:false,
})
proto.foo = 'zs';
console.log(proto.foo);
Object.getOwnPropertyDescriptor(proto,'foo').value
2.2 configurable属性
- 布尔值,决定了是否可以修改属性描述对象,当configurable:false,value、writable、enumerable、configurable都不能被修改。
let proto = {
foo:'foo',
foo1:'foo1',
}
Object.defineProperty(proto,'foo',{
configurable:false,
writable:false,
enumerable:false,
})
Object.defineProperty(proto,'foo',{
configurable:true,
})
Object.defineProperty(proto,'foo',{
writable:true,
})
Object.defineProperty(proto,'foo',{
enumerable:true,
})
Object.defineProperty(proto,'foo',{
value:1,
})
2.3 writable属性
- 布尔值,决定了目标属性的值,即value是否可被修改
let proto = {
foo:'foo',
foo1:'foo1',
}
Object.defineProperty(proto,'foo',{
writable:false,
})
proto.foo = 'zs';
console.log(proto.foo);
- 如果原型对象的某个属性的
writable为false,那么子对象将无法自定义这个属性
let proto = {
foo:'foo',
foo1:'foo1',
}
Object.defineProperty(proto,'foo',{
writable:false,
})
let obj = Object.create(proto);
obj.foo = 'zs';
console.log(obj.foo);
- 重定义子对象属性的可描述对象,解决原型对象的某个属性的
writable为false,子对象将无法自定义这个属性
let proto = {
foo:'foo',
foo1:'foo1',
}
Object.defineProperty(proto,'foo',{
writable:false,
})
let obj = Object.create(proto);
Object.defineProperty(obj,'foo',{
writable:true
})
obj.foo = 'zs';
console.log(obj.foo);
2.4 enumerable属性
- (可遍历性)返回一个布尔值,表示目标属性是否可遍历
- in会遍历
toString这一类实例对象继承的原生属性
var obj = {};
console.log('toString' in obj);
- 只有可遍历的属性,才会被
for...in循环遍历,规定toString这一类实例对象继承的原生属性,都是不可遍历的,这样就保证了for...in循环的可用性
enumerable:false时,以下三种操作不能使用该属性
- for...in
- Object.keys()
- JSON.stringify
- for...in循环会遍历出继承的属性,而Object.keys()不会,
Object.getOwnPropertyNames方法可获取对象自身的所有方法,包含可遍历和不可遍历。
2.5 存取器
- 适用于属性依赖于对象内部其他属性的场景
- 属性还可以用存取器(
accessor)定义,存值属性称为setter函数,使用属性描述对象的set属性;取值属性称为getter函数,使用属性描述对象的get属性
let proto = {
foo:'foo',
$foo:'foo',
}
Object.defineProperty(proto,'foo',{
get(){
return this.$foo;
},
set(value){
this.$foo = value
}
})
console.log(proto.foo);
proto.foo = 'fooNew';
console.log(proto.foo);
- 另一种写法:其中get不接受参数,set接受一个参数(即属性的值)
let obj = {
$name:'zs',
get name(){
return this.$name;
},
set name(value){
console.log('setter');
this.$name = value;
}
}
console.log(obj.name);
obj.name = 'li'
console.log(obj.name);