「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」。
defineProperty基本使用
对象添加属性的方式有很多种,defineProperty便是有一种,而且写起来还不太方便——不是吗!但存在即使合理的。
- 定义两个基础对象
var person = {
name: '张三',
sex: 0
}
var job = {
type: 'java',
time: 3,
age: 18
}
- enumerable控制属性是否可被枚举
Object.defineProperty(person,'age',{
value: 18
})
console.log(person,job)
变为可被枚举,只需要enumerable: true即可
Object.defineProperty(person,'age',{
value: 18,
enumerable: true // 默认是false
})
- writable控制属性是否可被修改
Object.defineProperty(person,'age',{
value: 18,
enumerable: true,
writable: true // 默认是false
})
person.age = 20
job.age = 21
console.log(person,job,Object.keys(person),Object.keys(job))
当 writable: false时
当 writable: true时
- configurable控制属性是否可被删除
Object.defineProperty(person,'age',{
value: 18,
enumerable: true,
writable: true,
configurable: true // 默认是false
})
delete person.age
delete job.age
console.log(person,job,Object.keys(person),Object.keys(job))
当 configurable: false时
当 configurable: true时
高级用法,数据代理
-
getter的使用,如下如,是否看出有何区别?首先person.age一开始他应该是(...)的,作为一个映射,当你点击(读取)时,他才回去真正去读取这个实际值
getter补充:即使get:function(){}放到一起(key:value)可以称之为getter,或者get函数称之为getter。下面的setter也应该也不难理解了。
- setter的使用,当一开始number=20,当通过修改number(第3步)的值,person.age在跟着变化,当改变person.age(第4步)时,number最后也跟着变化
- 总结,当两个看起来不相关的对象(变量),可通过Object.defineProperty()方法的getter和setter进行关联(映射、代理)起来,实现“同步更新”操作。
Vue中的应用
- 弄清楚Vue中的data定义的数据,我们看下图VsCode中的代码,当访问data中的数据,是否有以下两个疑问?
- 是否想到vm.data.name呢?
- data中的数据怎么可以vm.name下就能访问到?
解答问题1:
- vm.data确实存在,只不过把数据存放在vm._data中,验证如下
解答问题2:
- vm.name只不过是一个映射(代理)出来,当_data中的数据改变,则vm.name也被自动更新。
- 而真正实现数据互动,则是通过箭头3的getter和setter为变量name服务,从而实现读取时同步。
- 当我们通过实例vm去获取或者去更改,则同步修改vm.data.xxx数据。
- 虽然如解答1中所示vm._data===data,但是在_data中做了一下升级,这是作为劫持使用的,当数据被修改,通过viewModel中数据劫持(监听到数据变化)更新视图,这个在这里就不展开讲,后面单独出文。
总结:在Vue的data,做了一次数据代理,把data中的数据代理到实例上,为了编码变得更方便。