1.Object.defineProperty()是什么?
1-1 是vue2版本核心原理
1-2 MDN中的定义:
MDN定义为:Object.defineProperty()
方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性,并返回此对象。(是js的一个api,也是vue的核心之一)
通俗理解:更加精细化的定义(添加、修改)对象的属性
1-3 是JavaScript中一个api
2. 响应式特点
数据变了,能通知别人(页面更新)
就是由Object.defineProperty(对象,属性名,{set,get})
3.一个之前没用过的API:Object.getOwnPropertyDescriptor
API:Object.getOwnPropertyDescriptor(对象名,‘属性名’) 获取自己的属性描述
4. Object.defineProperty()格式及参数说明
格式:Object.defineProperty(obj,prop,descriptor)
4.1 obj : 要操作的对象
4.2 prop: 要定义或修改的属性的名称
4.3 descriptor:对参数2的描述,也叫属性描述符,他是一个具有固定属性名的字面量对象,如下:
{
4.3.1 value:underfined ,
// 初始值,该属性对应的初值。不写访问该属性就是underfined
4.3.2 .writable: false,
// 可写入,为true时,value属性值才能被修改,然后访问的话就是默认值
4.3.3 configurable:false ,
// 可配置,为true时,属性才能重新描述符或者删除。不能再次使用defineProperty去定义,定义就会报错。不能删除这个属性
4.3.4 enumerable:false,
// 可枚举,为true时,该属性才能出现在对象的枚举属性中,就是可以for循环。如果是false的话是不能遍历出来的
4.3.5 .函数1 set:function(){}
4.3.6 .函数2 get:function(){}
重点是俩函数,下面重点介绍
4.3.7 代码举例:
var obj = {a:1} Object.defineProperty(obj,'b',{ value:2 //初始2 ,不写就是underfined writable:false //writable如果是false,则不能修改这个值 }) obj.b = 200 //writable如果是false,则不能修改这个值,会默默反抗你,还是2 console.log(obj)
5.又一个没怎么用过的API:delete
delete 用来删除对象的属性
delete obj.a
6 小试牛刀
6.1 get 、set 拦截器(数据劫持)
var obj = {a:1} object.defineProperty(obj,'b',{ get:function(){console.log('有人正在访问b的值')} 有人访问b就会触发get set:function(newVal){console.log(`正在用${newval}设置属性b 的值`)} 有人设置就会触发set })
6.2 注意:
6.2.1 只用作拦截器,如果需要保存变量的值,则需要使用另一个单独存储的空间
6.2.2 value和writable 与 set、get 不能同时出现,会报错。
格式:object.defineProperty(obj,prop,{set,get})
// 需求;在你设置age属性的时候,如果属性>30岁,则修改成28 // 格式:object.defineProperty(obj,prop,{set,get}) //作用:拦截器 注意:只是拦截器,没法存,需借助第三方变量存 var obj = {name:'小王哥哥'} var age222 = 1 // 因为拦截器没法存,我定义一个变量来存值 object.defineProperty(obj,'age',{ get:function(){return age222}, set:function(newVal){ if(newVal > 30){ age222 = 28 //小王,你要注意,这里newVal不能保存啊,用第三方变量来保存! // 逻辑为当你obj.age = xx 设置的时候,如果值小于30输出1,大于30输出28 })
7.乞丐版的数据驱动视图
<div id='app'> 1 </div> //页面有个div内容为1 var obj = {a:1} // 定义一个对象 object.defineProperty(obj,'a',{ // 设置obj中a的属性值 set : function(newVal){ //set 是拦截器,是一个函数,可以做事啊。 当改变属性值的时候,会被拦截到,然后做事(set函数执行) //当我们通过obj.a=xxx修改的时候, 拦截器会把newval的值给div(innerHTML作用不必多说), 从而实现数据驱动视图 document.getElementById('app').innerHTML = newval } })
8.丐帮长老版
封装函数,监听对象的属性值变化
var obj = {a:1,b:2,c:3} //你如何得知,在什么事件,改了哪个属性? var newobj = {} // 定义新对象当做容器,中介,因为set不能保存值 //object.keys(obj) //拿键,放到数组里面 for in 同样可以 function objA(){ //封装成一个函数 //object.keys(obj) //拿键,放到数组里面 for in 同样可以 for(let key in obj){ <!--有疑问:为啥这里写的是newobj,原因在于他是拦截器,不能保存, 但是我们最终要改变的其实是obj所以newobj是一个中间人角色, 当个暂时的容器,方便修改obj --!> object.defineProperty(newobj,key,{ set : function(newval){ console.log{`有人修改了${key},新值是${newval}`} obj[key]=newval }, get : function(){return obj[key]} } } } objA() newobj.a = 100
9. 总结:
回到上篇文章核心,如何知道对象的属性值被修改了?
答案是:如果属性值被修改,set函数可以拦截到并且可以做事
1.通过这篇文章,学会了怎么使用这个api,监测对象的属性是否被修改
2.知道了原来对象不仅仅只有属性名属性值,还有那么多的其他东西
3.vue响应式的原理就是他
4.set和get就是一个拦截器,当你要改值或是要获取值就被拦截,在这俩函数里可以做事
5.他们只是拦截器,不具备保存值得作用,要保存值还是得定义个新的变量啊对象之类的接收
6.可以将他们封装成一个函数,随时调用