js中一切皆对象,而对象,本质上是一系列属性的集合.
对象的属性可分为:
命名属性 : 可直接通过“.”访问到的属性
数据属性 : 专门保存一个值的属性
访问器属性 : 保护数据属性的特殊属性
内部属性 : 不能通过“.”直接访问的属性 (比如 : class proto)
属性的Descriptor 四大特性:
getOwnPropertyDescriptor 查看属性四大特性
var person ={name:'Tom'};
console.log(Object.getOwnPropertyDescriptor(person,'name'));
// { value: 'Tom',
// writable: true,
// enumerable: true,
// configurable: true }
非defineProperty定义的属性,四大特性默认值都是true
- writable —— 是否为可写
- enumerable —— 是否为可枚举,
- configurable —— 是否为可配置的,false即不能再配置熟悉的特性,不可删除.
怎么设置属性的特性呢? defineProperty
另一个版本,一次定义多个属性 defineProperties
Object.defineProperty(person,'id',{
value:1717
});
console.log(Object.getOwnPropertyDescriptor(person,'id'));
// { value: undefined,
// writable: false,
// enumerable: false,
// configurable: false }
可见:defineProperty定义的属性,四大特性默认值都是false. 非defineProperty定义的属性,四大特性默认值都是true
下面看看这个特殊的属性:
person.id =199; // writable: false 不可写
console.log(person.id); //1717 没变 'strict'下直接报错
既然不可写,先通过defineProperty 把它变为可写
Object.defineProperty(person,'id',{
writable:true
});
忘记configurable: false 了吗,报错 TypeError: Cannot redefine property: id
不可逆的设置,重来:
Object.defineProperty(person,'id',{
value:1717,
writable:true,
configurable:true,
enumerable:false
});
好了,现在的person可写 可重新配置 就是不可枚举,for in 枚举不到id属性
for(let k in person){
console.log(k);
} //name
那么, 不可枚举的属性怎么才能访问呢? '.'访问和getOwnPropertyNames
console.log(person.id) // 1717
console.log(Object.keys(person)); //[ 'name' ] 顺便混进来
console.log(Object.getOwnPropertyNames(person)); //[ 'name', 'id' ]
访问器属性
访问器属性也是一种属性,他具有getter与setter两个回调函数,可控制或监控对某个属性的访问.
既然它是控制对别的属性的访问去了,那么它本身没有数据.
var c = {
_id: 1313, // 下划线开头, 语义上表示不能直接访问.
get id(){
console.log('取值',this._id);
return this._id;
},
set id(val){
console.log('存值', val);
this._id = val;
}
};
c.id=9090;
console.log(c.id);
// 存值 9090
// 取值 9090
// 9090
console.log(c._id); //9090 不通过访问器属性直接访问
注意一下: 'id' 这个访问器属性应该是可枚举的(没通过defineProperty定义),'id' '_id'都会遍历到:
console.log(JSON.stringify(c)); // stringify也是遍历取值
// 取值 9090
// {"_id":9090,"id":9090}
console.log(c); //{ _id: 9090, id: [Getter/Setter] }
通过defineProperty来设置访问器属性
访问器属性也是属性,也能像其它属性那样通过defineProperty来设置,不同的是,它没有value,而是get/set
Object.defineProperty(c,'ID',{
set:function(val){
console.log('存值ID', val);
this._id = val;
},
get:function(val){
console.log('取值ID',this._id);
return this._id;
},
enumerable:false, //默认false
configurable:true // 默认false
});
访问器属性和数据属性结合
var c = {
get id(){
console.log('取值',this._id);
return this._id;
},
set id(val){
console.log('存值', val);
this._id = val;
}
};
Object.defineProperty(c,'_id',{ // 内部属性不被枚举才对嘛
value:110,
writable:false,
enumerable:false, //默认false
configurable:true // 默认false
});
console.log(JSON.stringify(c));
//取值 110
//{"id":110}