vue 实现数据劫持 通过 new 避免溢出的原理是什么?

2023-06-22 308 0

最近开始尝试理解 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 时候,改的是新值。
这地方其实就是多了个函数立即执行,创造一个闭包而已。

回答

相关文章

nuxt2部署静态化和ssr的时候访问首页先报404再出现首页为什么?
`clip-path` 如何绘制圆角平行四边形呢?
多线程wait方法报错?
VUE 绑定的方法如何直接使用外部函数?
vue2固定定位该怎么做?
谁有redis实现信号量的代码,希望借鉴一下?