JS中的defineProperty

        在js中object.defineProperty方法能够让我们对对象的底层进行修改,例如:

        首先创建一个新对象

let obj = {
    "name" : "future",
    "age" : 21
    }

        再通过object.defineProperty方法对其值进行修改

object.defineProperty(obj, "age", {
    value: 22    
    })

console.log(obj.age) // 22

        在对对象的值修改后,我们再尝试使用对象赋值的方法来对值进行修改

obj.age = 18
console.log(obj.age) // 22

        可以看到使用对象赋值的方法失效了,这是因为使用object.defineProperty对对象的属性进行修改或赋值后,会默认将该属性变为不可修改,想再次修改的话只能通过其中增加writable:true的属性。

object.defineProperty(obj, "age", {
    value: 22   
    writable: true // 默认为false
    })

console.log(obj.age) // 22
obj.age = 18
console.log(obj.age) // 18

        在object.defineProperty这个方法中,还可以设置某一个属性是否可以被枚举(枚举就是循环对象所有的属性以及属性中包含的值)。字段为enumerable,默认值同样为false

object.defineProperty(obj, "age", {
    value: 22    
    })

console.log(obj.age) // 22
for (let prop in obj) {
    console.log(prop) // 只有name属性
    }

object.defineProperty(obj, "age", {
    value: 22   
    enumerable: true 
    })

console.log(obj.age) // 22
for (let prop in obj) {
    console.log(prop) // name和age属性
    }

        configurable属性用以控制前文中的writable以及enumerable属性以及configurable本身是否可以被修改,默认值为true

object.defineProperty(obj, "age", {
    value: 22    
    configurable: false 
    })

console.log(obj.age) // 22
for (let prop in obj) {
    console.log(prop) // 只有name属性
    }


object.defineProperty(obj, "age", {
    value: 22    
    enumerable: true // 让age可以被枚举
    })

console.log(obj.age) // 22
for (let prop in obj) {
    console.log(prop) // 还是只有name属性,因为configurable为false,导致enumerable不能被修改
    }


object.defineProperty(obj, "age", {
    value: 22    
    writable: true // 让age的值可以被修改
    })
obj.age = 18
console.log(obj.age) // 还是22,因为configurable为false,导致writable不能被修改

        接下来是object.defineProperty方法中的get()和set()方法,分别用于读取和设置对象中的值,其默认方法就是简单的读取和设置。如果想要在读取或设置对象中的值时截获该动作,就可以使用该方法对其进行重写。此方法可以用于数据的双向绑定和监听,vue中的数据双向绑定就是这样实现的。

object.defineProperty(obj, "age", {
    /* get(value) {
        return value
    },
    set(newValue) {
        age = newValue
    } */
    // 以上就是object.defineProperty方法中get和set的默认方法
    get() {
        return console.log("获取了age值", age)
    },
    set(newValue) {
        console.log("重写了age值", newValue)
        age = newValue
    }
})

console.log(obj.age) // 获取了age值22
obj.age = 18 // 重写了age值18

        有了这种方法后我们就可以实现对数据的监听,并且当对象中数据改变出发set方法的时候只需要使用DOM方法获取到数据的渲染块,就可以实现一个简单的数据绑定

<body>
    <input id='ipt' type='text'>
</body>

<script>
    let ipt = document.getElementById('ipt');
    let obj = {};
   
    object.defineProperty(obj, "age", {
         value: 18
         get() {
            return console.log("获取了age值", age)
         },
         set(newValue) {
            console.log("重写了age值", newValue)
            age = newValue
            ipt.innerText = age
         }
    })
    // 写一个input的数据监听
    ipt.addEventListener('input', (el)=> {
        obj.age = el.target.value
    })
</script>