美文网首页JavaScript
defineProperty详解

defineProperty详解

作者: 我是一个前端 | 来源:发表于2019-01-04 15:47 被阅读0次

    搁置了几天我还是决定再次重写!

    下边我们来具体聊聊先从defineProperty开始说起

    defineproperty

    //defineproperty 有个定义object属性的功能,应该没几个人用,因为相对于obj.a = 1这种方式简直不能再难用。
    
    //通常我们定义obj属性
    let obj = {
          a:1
    }
    obj.b = 2
    obj['c'] = 3
    console.log(obj)//{a: 1, b: 2,c: 3}  
    
    Object.defineProperty(obj,'d',{
          value: 4
    })
    
    console.log(obj)//{a: 1, b: 2,c: 3,d:4}  //defineProperty可以定义对象属性
    
    //也可以修改
    Object.defineProperty(obj,'b',{
          value: 5
    })
    console.log(obj)//{a: 1, b: 5, c: 3, d: 4}
    

    //对你没看错defineProperty有这个功能,不知可以定义新的属性还可以修改,这么逆天难用的功能为什么还要造出来?说这个有什么用?别急往下看

    descriptor详解

    defineProperty 接收三个参数
    • object (必须有 操作的对象本身 这个很容易理解不传它操作谁?)

    • propertyname (必须有 属性名 添加修改属性得有属性名)

    • descriptor (必须有 官方说的我理解不了,我理解的是 属性描述
      1、简单点就是 设置属性的值value,
      2、是否可操作属性值 writable,
      3、是否可修改配置configurable如果值为false descriptor内的属性都不可操作
      4、是否可枚举enumerable

      *descriptor内配置可有可无,value默认undefind,其余默认为false

    先做了介绍我们下边来证明下

    writable
    //栗子还是这个栗子
            let obj = {
                a: 1
            }
            Object.defineProperty(obj, 'b', {
                value: 2,
                writable: false//不可修改
            })
    
            obj.b = 3
            console.log(obj) //{a: 1, b: 2} 还真是不可以
            //难道是姿势不对?
            Object.defineProperty(obj, 'b', {
                value: 3
            })
            console.log(obj)//{a: 1, b: 2} 一样的效果 和姿势无关。
    
    
    configurable

    //configurable 这个比较厉害 控制descriptor内属性都不可改变不知道是不是真的

    //还是这个栗子

           let obj = {
                a: 1
            }
            Object.defineProperty(obj, 'b', {
                value: 2,
                //writable: false//不可修改
                configurable: false
            })
            obj.b = 5
            console.log(obj)//[1,2]
    
    enumerable

    对否可枚举

     let obj = {
                a: 1
            }
            Object.defineProperty(obj, 'b', {
                value: 2,
                //writable: false//不可修改
                //configurable: false
                enumerable: false
            })
            //obj.b = 5
            console.log(Object.keys(obj))//["a"]
    

    接了下来说到重点: set和get这也是vue3.0前observe的实现原理

    let obj = {
                a: 1
            }
    
            let newValue = 45
            Object.defineProperty(obj, 'b', {
                get(value) {
                    console.log('获取')
                    return value
                },
                set(newValue) {
                    console.log('设置')
                    value = newValue
                }
            })
            obj.b = 6 //设置
    
            obj.b //获取
    

    知道用法了我们来实践一下

          //html
          <div></div>
          <input type="text">
          //js
          //类似 vue的data
            let obj = {}
    
            /*
             *obj      要劫持的对象
             *name     要劫持对象的属性
             *callback 劫持以后的操作
             */
            function watch(obj, name, callback) {
                let value = obj.name
                Object.defineProperty(obj, name, {
                    set(msg) {
                        // 触发setter给obj赋值
                        value = msg
                            //执行劫持后的操作
                        callback(value)
                    },
                    get() {
                        //返回获取属性值
                        return value
                    }
                })
            }
    
            //
            function doSomething(value) {
                document.querySelector('div').innerHTML = value
                document.querySelector('input').value = value
            }
            //监听input变化 
            //可以参考全兼容版:https://segmentfault.com/a/1190000017524278
            document.querySelector('input').addEventListener('input', (e) => {
                obj['msg'] = e.target.value
            })
    
            watch(obj, 'msg', doSomething)
    

    效果:
    1、input输入改变div内容


    image.png

    2、改变obj name属性


    image.png
    3、获取改变后的obj属性name
    image.png

    简单的用defineProperty实现了双向绑定

    欢迎吐槽!您的点赞是我继续的动力!谢谢

    相关文章

      网友评论

        本文标题:defineProperty详解

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