Object.defineProperty的理解大家都很熟悉了,废话不多说。从Vue源代码开始,删除了一些不相关的代码/***在对象上定义一个响应式属性。*/exportfunctiondefineReactive(obj:Object,key:string,val:any,customSetter?:?Function,//非必需参数shallow?:boolean//非必需参数){//这里的属性会解释belowconstproperty=Object.getOwnPropertyDescriptor(obj,key)if(property&&property.configurable===false){return}//迎合预定义的getter/setterconstgetter=property&&property.getconstsetter=property&&property.set//Object.defineProperty的set和get属性的默认值在处理前未定义//arguments.length===2表示不传入val参数if((!getter||setter)&&arguments.length===2){val=obj[key]}Object.defineProperty(obj,key,{get:functionreactiveGetter(){//注意,上面解释了getter的默认值为undefinedconstvalue=getter?getter.call(obj):val返回值},set:functionreactiveSetter(newVal){//注意,上面解释过,setter的默认值是undefinedconstvalue=getter?getter.call(obj):valif(newVal===value||(newVal!==newVal&&value!==value)){return}if(getter&&!setter)returnif(setter){setter.call(obj,newVal)}else{//注意,这里,下面会解释解释val=newVal}}})}问题一:什么是constproperty=Object.getOwnPropertyDescriptor(obj,key)?简而言之,Object.getOwnPropertyDescriptor()方法返回指定对象上自身属性对应的属性描述符更详细的请看这个letdata={form:{name:'ShaneHu',sex:'male'}}letdescriptor=Object.getOwnPropertyDescriptor(data,'form');console.log(descriptor)的执行结果上面代码的:{"value":{"name":"ShaneHu","sex":"male"},"writable":true,"enumerable":true,"configurable":true}数据处理后objectwithObject.defineProperty:letdata={form:{name:'ShaneHu',sex:'male'}}functionobserve(data,key){//声明内部变量letvalue=data[key]Object.defineProperty(data,key,{get(){returnvalue},set(newValue){if(value===newValue)return;value=newValue}})}observe(data,'form')让描述符=Object.getOwnPropertyDescriptor(data,'form');console.log(descriptor)上面代码的执行结果:{"enumerable":true,"configurable":true,"get":get(),"set":set(newValue)}所以,常量值=getter?getter.call(obj):val返回的其实是之前赋值的obj[key]。//Object.defineProperty的set和get属性的默认值在处理之前是undefined。//arguments.length===2表示没有传入val参数if((!getter||setter)&&arguments.length===2){val=obj[key]}那么,问题2:why是val=newVal,不是obj[key]=newValif(setter){setter.call(obj,newVal)}else{val=newVal}一开始我写Object.defineProperty的时候直接写obj[key]=newVal在set方法中,结果自然是错误的。下面是我根据Vue源码重写的简化版数据劫持,方便理解:functionobserve(data,key,val){//declareinternalvariablesletvalue=val||数据[键];Object.defineProperty(data,key,{get(){returnvalue},set(newValue){if(value===newValue)return;value=newValue}})}1.这个方法是一个闭包,value是函数内的局部变量;2.set方法,我们可以理解为它不是直接修改data对象下某个属性的值,而是修改局部变量value的值;3.所以get方法并没有返回data对象下某个属性的值。但是局部变量值;
