最近开始尝试理解 vue 实现 mvvm 实时响应的原理,有一个地方不理解,抽离出来的代码模型如下:
let data={
name:"张三",
add:'山东',
}
const keys=Object.keys(data)
// 方案一
const obs=new function (obj){
keys.forEach((k)=>{
Object.defineProperty(this,k,{
get(){
return obj[k]
},
set(val){
console.log(`${k}被改了,我要去解析模板.....`)
obj[k]=val
}
})
})
}(data)
// 方案二
// const obs ={}
// keys.forEach((k)=>{
// Object.defineProperty(obs,k,{
// get(){
// return data[k]
// },
// set(val){
// console.log(`${k}被改了,我要去解析模板.....`)
// data[k]=val
// }
// })
// })
const vm={}
vm._data=data=obs
其中,方案二会产生溢出我能理解,vm._data=data=obs 后vm._data 和 data 就指向了同一个对象,当读取该对象的一个属性时会调用其set,set中return又要重新读取这个属性无限循环导致溢出。
但是为什么方案一(源码中抽离出来的模型),就不会产生这个问题?它和方案二的区别不就是使用new 函数创建的对象吗?但是最后也赋值给 vm._data 和 data 了,为什么就可以避免溢出呢?
单看一次执行,这两个写法都是正确的;
但是如果第二次执行,data 会被修改掉
`
let data = {}
// 省略上诉代码
// 在初始化下一个组件时候
data = {
}
`
此时之前的defineProperty
在 set 时候,改的是新值。
这地方其实就是多了个函数立即执行,创造一个闭包而已。