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

2023-06-28 0 2,768

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

方案一中,通过立即执行函数创建的观察者对象(obs)内部的obj变量指向的是全局的data对象。在执行完vm._data=data=obs后,data的指向发生了变化,指向了obs对象。此时,如果要访问原来data指向的对象,只能通过obs内部的obj来访问。

在方案二中,没有类似于方案一中的obj变量来引用原来data指向的对象。在执行完vm._data=data=obs后,就没有办法再访问到原来data指向的对象了。此时,对data进行修改或访问实际上是在访问新创建的obs对象,而obs对象内部又依赖于data,这就形成了一个循环引用的情况,导致溢出错误。

在方案二中可以创建一个变量来引用 data 原来指向的对象,以此来保留对其的访问和修改途径,如下:

        // 方案二
        const obs ={}
        keys.forEach((k)=>{
            // 通过 timeObj 指向原对象的引用
            let timeObj=data
            Object.defineProperty(obs,k,{
                get(){
                    return timeObj[k]
                },
                set(val){
                    console.log(`${k}被改了,我要去解析模板.....`)
                    timeObj[k]=val
                }
            })
        })
收藏 (0) 打赏

感谢您的支持,我会继续努力的!

打开微信/支付宝扫一扫,即可进行扫码打赏哦,分享从这里开始,精彩与您同在
点赞 (0)

1. JK下载官网所有资源来源于开发团队,加入会员即可下载使用!如有问题请联系右下角在线客服!
2. JK下载官方保障所有软件都通过人工亲测,为每位会员用户提供安全可靠的应用软件、游戏资源下载及程序开发服务。
3. JK开发团队针对会员诉求,历经多年拥有现今开发成果, 每款应用程序上线前都经过人工测试无误后提供安装使用,只为会员提供安全原创的应用。
4. PC/移动端应用下载后如遇安装使用问题请联系右下角在线客服或提交工单,一对一指导解决疑难。

JK软件下载官网 技术分享 vue 实现数据劫持 通过 new 避免溢出的原理是什么? https://www.jkxiazai.com/1892.html

JK软件应用商店是经过官方安全认证,保障正版软件平台

相关资源

官方客服团队

为您解决烦忧 - 24小时在线 专业服务