• 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}
    
  • 相关阅读:
    HDU4812 D Tree(树的点分治)
    BZOJ1834 [ZJOI2010]network 网络扩容(最小费用最大流)
    HDU4862 Jump(放大边权的费用流)
    SCU3185 Black and white(二分图最大点权独立集)
    HDU3729 I'm Telling the Truth(字典序最大的最大流)
    HDU3586 Information Disturbing(树形DP)
    HDU3657 Game(最小割)
    POJ3162 Walking Race(树形DP+尺取法+单调队列)
    SCU3312 Stockholm Knights(最大流)
    Codeforces 161D Distance in Tree(树的点分治)
  • 原文地址:https://www.cnblogs.com/ShawSpring/p/10806841.html
Copyright © 2020-2023  润新知