• 第三章 属性高级


    一、属性描述符

    1.获取对应属性的描述符

    属性描述符:属性的特征;也叫元属性;修饰属性的属性

    Object.getOwnPropertyDescriptor(obj,"name"); 第一个参数:对应的对象 第二个参数:对应对象的属性


      var obj={
      name:"wql",
      age:38,
      wife:"lss"
     
    }
      var res=Object.getOwnPropertyDescriptor(obj,"wife");
      console.log(res)
    //res是一个对象
    {
      1. configurable: true
      2. enumerable: true
      3. value: "lss"
      4. writable: true
      5. __proto__: Object
    }

    2.为对象新增或修改属性

    var obj={
        name:"snw"
    };
    Object.defineProperty(obj,"age",{
        value:18,
        writable:true,
        configurable:true,
        emumerable:true
    });
    console.log(obj); //Object {name: "snw", age: 18}
    console.log(obj.age);//18
     
     
     
     
    属性描述符的默认值都是false

    3.writable(可写的)

    writable决定是否可以修改属性的值
     
    当writable为false时,对应的属性的值是无法修改的。
     // writable为false 时 configurable一般也为false 在默认情况下: 继续修改的话会静默失败 在严格模式下: 会报错

    var obj={
    name:"Lebron",
    age:33,
    team:"湖人"
    }
    //obj.team="骑士"; 位置在这儿能被修改
    Object.defineProperty(obj,"team",{
    writable:false
    })
    obj.team="热火";
    console.log(obj);

    4.configurable(可配置的)

    configurable来决定属性是否可以配置
    可配置:属性能否重新定义 属性能否删除 当configurable为false时,对应的属性是无法重新定义的,无法删除的。但该对象是还可以继续添加属性的。 默认情况下
    进行重新定义会报错
    进行删除会静默失败 注意一个小小的例外: 当configurable为false时,writable可以进行重新定义,但只满足由writable:
    true ==> writable:false

       var obj={
           name:"zyy",
           age:20,
           hobby:"eat"
         }
         Object.defineProperty(obj,"hobby",{
          //value:"play",
            writable:true,
            configurable:false,
            enumerable:false
        })

         delete obj.hobby;
         console.log(obj);

    5.enumerable

    //enumerable可枚举:控制了属性的可枚举权限
    //可枚举:能否出现在对象的for in 循环中
    
    
    
    var obj={
        name:"zyy",
        age:26,
        behavior:"play basketball"
    }
    Object.defineProperty(obj,"behavior2",{
        value:"eat",
        enumerable:false
    })
    
    for(var item in obj){
      console.log(item);
    }

    6.严格模式

    <!--
        严格模式的语法比较严谨
            没有通过var定义的变量 在严格模式底下就会报错
            this的指向
                普通调用时 如果是严格模式 那this指向undefined
       严格模式的管理范围:作用域

       在属性描述符writable为flase的情况下 对属性值进行修改 就会报错不会静默失败
       在属性描述符configurable为flase的情况下 对属性进行删除 就会报错不会静默失败

    -->
    <script>
        function test() {
            "use strict"
            inner();
            function inner() {
                console.log(this)
            }
        }
        
        (function () {
            "use strict"
            test()
        })()

    7.属性的指定方式

    /*属性的指定方式:
           1. 字面量初始化的时候直接通过 键值对的形式指定
                    属性描述符的默认值基本都是true
           2. 通过对象点的形式来指定
                    属性描述符的默认值基本都是true
           3. 原始的指定形式的方式
    `               属性描述符的默认值基本都是false
                   value:undefined
            4. var a = "a"; 给window添加的属性
                    configurable: false
                    enumerable: true
                    writable: true
            5.    b="b";给window添加的属性
                属性描述符的默认值基本都是true
       */
    
        var a = "a";
        b="b";
        console.log(Object.getOwnPropertyDescriptor(window,"a"))
        console.log(Object.getOwnPropertyDescriptor(window,"b"))
        delete  a;
        delete  b;
        console.log(a);
        console.log(b);

    8.存在性检查

    var obj={
            a:undefined,
            wife:{
                name:"xxx"
            }
        };
        console.log(obj.a);
    
        //in关键字 会影响对象的直接属性 也访问原型链  可是不访问对象的深层属性
        console.log("a" in obj)
        console.log("b" in obj)
        console.log("toString" in obj)
        console.log("name" in obj,"------")
    
        //在js中所有的方法都是 浅不变形 的;只会影响对象的直接属性 不访问原型链 也不访问对象的深层属性
        console.log(obj.hasOwnProperty("a"));
        console.log(obj.hasOwnProperty("b"));
        console.log(obj.hasOwnProperty("toString"));
        console.log(obj.hasOwnProperty("name"));
    
        var res = Object.getOwnPropertyNames(obj);
        console.log(res);

    9.访问描述符(get&&set)

        // 属性描述符 : 属性的特征  属性的属性
        // 数据描述符 : 具有writable 和 value属性描述符 的属性!
        // 访问描述符 : 具有set 和 get属性描述符 的属性!

        var obj={
            get age(){
            return obj.__age__;
             },
           set age(val){
                if (val > 150){
                   val =150;
           }else if(val < 0){
                   val =0;
             }

    
    

          obj.__age__=val;
           }
       }

    
    

    obj.age=33;
    console.log(obj.age);

    二、对象不变性

    1.对象常量属性

    将属性的writable和configurable设置为false

          var MathCopy = {};
          Object.defineProperty(MathCopy,"PI",{
               value:3.141592654,
               writable:false,
               configurable:false,
               enumerable:true
          })
           MathCopy.PI=1;
          console.log(MathCopy.PI)



    2.禁止对象扩展

    由于属性描述符是对属性的管理
     
    所以想禁止对象扩展不能使用属性描述符来控制,而是需要调用Object.preventExtensions(obj);
     
    参数:要求禁止扩展的对象
     
     
    默认情况下
        为对象添加新的属性会静默失败
    严格模式底下
        报错
     
     
    注意:禁止对象扩展只是禁止了对象去扩展属性,
    而之前的属性是可以进行重新定义或者删除的,
    属性值也是可以修改的

    3.密封对象

    在禁止对象扩展(Object.preventExtensions(obj);的基础上把现有属性的configurable都调整为false
      
    调用Object.seal(obj)密封一个对象
      
    密封之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,但属性值是可以修改的

     var obj = {
            a:"a",
            b:'b'
        };
        Object.seal(obj);

    
    

           delete obj.a;
           obj.c="c";
           obj.a="aa";
        console.log(obj);

    输出:{a: "aa", b: "b"}   没有被删除,也没有添加c

    4.冻结对象(浅)

    
    

        在密封对象(Object.seal(obj))的基础上把现有属性的writable都调整为false

        调用Object.freeze(obj)密封一个对象

       冻结之后禁止了对象去扩展属性,原有的属性不可以进行重新定义或者删除,属性值不可以进行修改




    var
    obj = { a:"a", b:'b' }; Object.freeze(obj); delete obj.a; obj.c="c"; obj.a="aa"; console.log(obj);

    5.冻结对象(深)

    <script>
        var obj = {
            name: "zyy",
            age: 20,
            hobby: {
                No1: "playball",
                No2: "eat",
                No3: "sleep"
            }
        }
       
        function deep(obj) {
            var keys = Object.getOwnPropertyNames(obj);
            keys.forEach(function (key) {
                var val = obj[key]
                if (Object.prototype.toString.call(val) === "[object Object]") {
                    deep(val)
                }
    
            });
            return Object.freeze(obj)
    
        }
    deep(obj);
    obj.hobby.No1="watch";
    console.log(obj)
    
    
    </script>

    三、属性查找和设置

    1.基本规则

    /* 数据描述符
            configurable: true
            enumerable: true
            writable: true
    */
    
        // 查找: 先在对象的直接属性中找 找到了就返回 找不到上原型链 整体原型链都没有 返回 undefined
        // 设置: 只影响对象的直接属性

    2.完整的规则(查找)

     // [[Get]]:代表的属性查找的算法
            // [[Get]]:
            //     1.在对象中查找是否具有相同名称的属性,如果找到,就会返回这个属性的值。
            //     2.如果没有找到,则遍历原型链
            //     3.无论如何都没找到,返回undefined
            //     4.访问描述符具体看get方法的逻辑

    3.完整的规则(设置)

    /*
        [[Put]]:代表的属性设置的算法
    
        obj.a="a";
        [[put]]:
            1.
                如果属性直接存在于对象中 不在原型链上
                找到直接存在于对象中的属性
                -数据描述符(没有setter/getter)
                    直接修改对象中的属性(注意writbale的值)
                -访问描述符
                    直接调用set方法
            4.
                如果属性直接存在于对象中  也在原型链上
                找到直接存在于对象中的属性
                -数据描述符(没有setter/getter)
                    直接修改对象中的属性(注意writbale的值)
                -访问描述符
                    直接调用set方法
            2.
                如果属性不直接存在于对象中也不在原型链上
                在对象的直接属性中添加一个属性(数据描述符)
                    value:"a"
                    writable:true
                    configurable:true
                    enumerable:true
    
        3.
            如果属性不直接存在于对象中  在原型链上
                 ①.该属性是数据描述符(没有setter/getter)
                    -writbale为true
                        直接在对象中添加一个属性,我们称之为屏蔽属性
    (√)(√)(√)(√)-writbale为false
                        报错,不会生成屏蔽属性
    
    (√)(√)(√)(√) ②.该属性是访问描述符
                    调用set,不会生成屏蔽属性
        */
    
        // Object.prototype.a="a";
        Object.defineProperty(Object.prototype,"a",{
            set:function(val){
    
            }
        })
        var obj={};
        obj.a="aaaa";
        console.log(obj,Object.prototype)
    </script>

    object

    静态方法
        Object.create()
        Object.defineProperty()
        Object.getOwnPropertyDescriptor()
        Object.getOwnPropertyNames()
        Object.preventExtensions()
        Object.seal()
        Object.freeze()
        Object.keys()
    实例方法
        Object.prototype.toString()
        Object.prototype.valueOf()
        Object.prototype.propertyIsEnumerable()
  • 相关阅读:
    蓝翔杯子校内赛练习代码
    [蓝桥杯][算法训练VIP]猴子分苹果
    系统设计部分代码
    坐标离散化
    蒟蒻吃药计划-治疗系列 #round 1 机器分配+挖地雷
    蒟蒻吃药计划
    F小蒟蒻教你卡常
    最长不下降子序列
    最大子段和(DP)
    luogu P1216 (USACO1.5) Number Triangles
  • 原文地址:https://www.cnblogs.com/fxiong/p/10163856.html
Copyright © 2020-2023  润新知