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>