美文网首页
快速理解Object.defineProperty( )

快速理解Object.defineProperty( )

作者: chenM_ | 来源:发表于2019-06-17 15:30 被阅读0次

    原文地址

    关于Object.defineProperty()

    MDN解释:Object.defineProperty()方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。

    本文简单的讲解了 Object.defineProperty 有助于你快速了解 Object.defineProperty 想要详细学习请移至MDN文档

    我的理解就是 当你操作一个对象(修改或者删除属性)时,Object.defineProperty可以控制是否可以去操作这个对象(修改、删除属性)或者修改、获取属性值时拦截你的操作然后do something。

    语法 Object.defineProperty(obj, prop, descriptor)

    
    obj 要操作的对象
    
    prop 要定义或修改的属性的名称
    
    descriptor 将被定义或修改的属性描述符
    
    

    先看一下基本使用,然后下面会具体讲解一下属性描述符。

    
    var obj = {};
    
    Object.defineProperty(obj,'name',{
    
        value:'chenm'
    
    });
    
    console.log(obj.name); //chenm
    
    

    descriptor属性描述符

    分为数据描述符和存取描述符

    
    configurable:为 true 时,该属性描述符才能够再次被改变,同时该属性也能从对应的对象上被删除。默认为 false。
    
    enumerable:为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
    
    value:该属性的值,默认为 undefined。
    
    writable:为true时,属性的值才能被 ‘=’ 赋值。默认为 false。
    
    get:一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问(获取)该属性时,该方法会被执行,方法执行时没有参数传入,
    
    但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。
    
    set:一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当修改属性值时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
    
    
    configurable:为 true 时,该属性描述符才能够再次被改变,同时该属性也能从对应的对象上被删除。默认为 false。
    
    //1.configurable为false
    
    var obj = {age:25};
    
    Object.defineProperty(obj,'name',{
    
        configurable:false,
    
        value:'chenm'
    
    });
    
    delete obj.name;
    
    console.log(obj.name); //chenm
    
    //configurable 为false时(当然默认就为false),name不允许被删除,所以打印obj.name 还是chenm
    
    //注意当操作对象现有属性的时候 configurable默认为true
    
    //2.configurable为 true
    
    Object.defineProperty(obj,'age',{
    
        value:'26'
    
    });
    
    delete obj.age;
    
    console.log(obj.age); //undefined
    
    
    enumerable:为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
    
    //1.enumerable为false
    
    var obj = {age:25};
    
    Object.defineProperty(obj,'name',{
    
        enumerable:false,
    
        value:'chenm'
    
    });
    
    for(let key in obj){
    
        console.log(key)    //age
    
    }
    
    console.log(Object.keys(obj))//["age"]
    
    //Object.keys:返回该对象可枚举属性组成的数组。 enumerable为false时,name并不能枚举。
    
    //注意当操作对象现有属性的时候 enumerable默认为true
    
    //2.enumerable为true
    
    var obj = {age:25};
    
    Object.defineProperty(obj,'name',{
    
        enumerable:true,
    
        value:'chenm'
    
    });
    
    for(let key in obj){
    
        console.log(key) //age name
    
    }
    
    console.log(Object.keys(obj)) //["age","name"]
    
    
    value:该属性的值,默认为 undefined。
    
    var obj = {};
    
    Object.defineProperty(obj,'name',{
    
        value:'chenm'
    
    });
    
    console.log(obj.name); //chenm
    
    Object.defineProperty(obj,'sex',{
    
    
    
    });
    
    console.log(obj.sex); //undefined
    
    //不设置value时 改属性的值为 undefined
    
    
    writable:为true时,属性的值才能被 ‘=’ 赋值。默认为 false。
    
    //1.writable为false
    
    var obj = {};
    
    Object.defineProperty(obj,'sex',{
    
        writable:false,
    
        value:'boy'
    
    });
    
    console.log(obj.sex); //boy
    
    obj.sex = 'girl';
    
    console.log(obj.sex); //boy
    
    //writable 为false(默认就为false),sex是不能用'='赋值的。
    
    //2.writable为true
    
    var obj = {};
    
    Object.defineProperty(obj,'sex',{
    
        writable:true,
    
        value:'boy'
    
    });
    
    console.log(obj.sex)  //boy
    
    obj.sex = 'girl'
    
    console.log(obj.sex)  //girl
    
    
    get:一个给属性提供 getter 的方法。当访问(获取)该属性时,该方法会被执行。
    set:一个给属性提供 setter 的方法。当修改该属性值时,该方法会被执行。
    
    var obj = {};
    
    let val = '15k';
    
    Object.defineProperty(obj,'wages',{
    
        get:function(){
    
        //这是里获取属性的时候执行
    
        console.log('我获取到你的值了。。。')
    
        return val;
    
        },
    
        set:function(newVal){
    
            //这是里修改属性值的时候执行
    
            console.log('我修改了你的值。。。')
    
        val = newVal
    
        }
    
    });
    
    console.log(obj.wages);
    
    obj.wages = '20k'
    
    console.log(obj.wages);
    
    //我获取到你的值了。。。
    
    //15k
    
    //我修改了你的值。。。
    
    //我获取到你的值了。。。
    
    //20k
    
    
    
    //get,set一起出现,如果省略get,获取到的值都是undefined
    
    var obj = {};
    
    let val = '15k';
    
    Object.defineProperty(obj,'wages',{
    
        set:function(newVal){
    
            //这是里修改属性值的时候执行
    
            console.log('我修改了你的值。。。')
    
            val = newVal
    
        }
    
    });
    
    console.log(obj.wages) //undefined
    
    obj.wages = '20k'
    
    console.log(obj.wages)//undefined
    
    //如果省略set, 无法赋值。
    
    var obj = {};
    
    let val = '15k';
    
    Object.defineProperty(obj,'wages',{
    
        get:function(){
    
        //这是里获取属性的时候执行
    
        console.log('我获取到你的值了。。。')
    
        return val;
    
        },
    
    });
    
    console.log(obj.wages) //15k
    
    obj.wages = '20k'
    
    console.log(obj.wages)//15k
    
    

    注意:

    
    //get,set与writable,value不能共用
    
    var obj = {};
    
    let val = '15k';
    
    Object.defineProperty(obj,'wages',{
    
        value:'20k'
    
        set:function(newVal){
    
            //这是里修改属性值的时候执行
    
            console.log('我修改了你的值。。。')
    
        val = newVal
    
        }
    
    });
    
    //Uncaught SyntaxError: Unexpected identifier
    
    

    tips:操作对象的现有属性和用Object.defineProperty()添加的属性,描述符的默认值是有所的同的。

    
    现有属性描述符默认值:
    
    configurable:true
    
    enumerable:true
    
    writable:true
    
    Object.defineProperty()添加的属性描述符默认值:
    
    configurable:false
    
    enumerable:false
    
    writable:false
    
    

    根据Object.defineProperty()的get,set写一个简单的数据双向绑定。

    <!DOCTYPE html>
    
    <html>
    
        <head>
    
        <meta charset="UTF-8">
    
        <title></title>
    
        </head>
    
        <body>
    
        <input type="text" id="input"/>
    
        <span id="text"></span>
    
        <button id="btn1">获取值</button>
    
        <button id="btn2">修改值</button>
    
        <script>
    
            var obj = {
    
                value:123
    
            };
    
            //初始化赋值
    
            document.getElementById('input').value = obj.value;
    
            document.getElementById('text').innerHTML = obj.value;
    
    
    
            //监听input方法
    
            document.getElementById('input').oninput = function(e){
              obj.value = e.target.value;
            };
          //使用Object.defineProperty设置属性的get,set方法。
            let val = obj.value;
            Object.defineProperty(obj,'value',{
              get:function(){
                  return val
              },
              set:function (newVal){
                  //当值被修改的时候 修改input&span的值
                  document.getElementById('input').value = newVal;
                  document.getElementById('text').innerHTML = newVal;
                  val = newVal;
               }
            });
            document.getElementById('btn1').onclick = function (){
              console.log(obj)
            }
           document.getElementById('btn2').onclick = function (){
              obj.value = '修改了';
            }
        </script>
        </body>
    </html>
    
    

    相关文章

      网友评论

          本文标题:快速理解Object.defineProperty( )

          本文链接:https://www.haomeiwen.com/subject/qmwafctx.html