js 属性的那些事

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}

猜你喜欢

转载自www.cnblogs.com/ShawSpring/p/10806841.html