javascrip中的数据劫持与数据代理

简介: javascrip中的数据劫持与数据代理

一、用Object.defineProperty实现数据劫持

1.VUE2中的响应式原理

当你把一个普通的 JavaScript 对象传入 Vue 实例作为 data 选项,Vue 将遍历此对象所有的 property,并使用

Object.defineProperty 把这些 property 全部转为

getter/setter。Object.defineProperty 是 ES5 中一个无法 shim 的特性,这也就是 Vue 不支持

IE8 以及更低版本浏览器的原因。

这些 getter/setter 对用户来说是不可见的,但是在内部它们让 Vue 能够追踪依赖,在 property

被访问和修改时通知变更。这里需要注意的是不同浏览器在控制台打印数据对象时对 getter/setter 的格式化并不同,所以建议安装

vue-devtools 来获取对检查数据更加友好的用户界面。

每个组件实例都对应一个 watcher 实例,它会在组件渲染的过程中把“接触”过的数据 property 记录为依赖。之后当依赖项的

setter 触发时,会通知 watcher,从而使它关联的组件重新渲染

也就是说vue对data选项的所有property加了监听,当数据变化时,vue2中每一个实例都有一个watcher进行依赖收集,也就是这个实例所关联的property。property变化时候被setter监听到,然后通知watcher再进行后续处理。

2.用一个Object.defineProperty实现一个简单的数据劫持

    let a = {
        name: "小红",
        age: 12,
        oinfo: {
            school: "狗屁大学",
            hobby: ["football", "pingpang"]
        },
    }

    const observer = function (data) {

        if (!data || typeof data !== 'object') {
            return
        }
        for (const key in data) {
            if (Object.hasOwnProperty.call(data, key)) {
                let currentData = data[key]
                observer(currentData)
                Object.defineProperty(data, key, {
                    enumerable: true,
                    configurable: false,
                    get() {
                        console.log(`调用数据时候:${key}数据被劫持劫持`);
                        return currentData
                    },
                    set(value) {
                        console.log(`设置数据时候:${key}数据被劫持劫持`);
                        currentData = value
                    }
                })
            }
        }
    }
    observer(a)
    a.oinfo.hobby = ["1", "2"]
    console.log(a.oinfo.hobby);

通过observer这个方法,我们把对象a里面的所有property进行了劫持,在对property进行get和set的时候我们就可以做自己想做的事情了,比如说进行标记的添加之类的,当然这里只是简单的实现,在vue中为了能够更深度的监听数组的变化vue重写了数组的方法。

  const extendedArr = Object.create(Array.prototype)
    //重写这几个方法,用Object.assign把新的方法混入到Array.prototype上
    const methods = ["push", "pop", "shift", "splice", "sort", "reverse"]
    methods.forEach(method => {
        const oldm = Array.prototype[method]
        const newm = function (...args) {
            oldm.apply(this, args)
            console.log(`劫持方法,爱干嘛干嘛`)
        }
        extendedArr[method] = newm
    })

二、用Proxy实现数据劫持

1.原理

Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。

一个代理类的简单例子:

  let student = {
        name: "小红",
        age: 15
    }
    student = new Proxy(student, {
        set(obj, prop, value) {
            if (prop == "age" && typeof value !== "number") {
                throw new Error("年龄必须是数字")
            }
            Reflect.set(...arguments)
        },
        get(obj, prop) {
            console.log("get操作");
            return Reflect.get(...arguments)
        }
    })

上面代码把student这个对象进行了代理,判断一下age属性,当age不是number时候就报错。

1.在VUE3中实现响应式核心变成了代理模式

当把一个普通的 JavaScript 对象作为 data 选项传给应用或组件实例的时候,Vue 会使用带有 getter 和 setter的处理程序遍历其所有 property 并将其转换为 Proxy 。这是 ES6 仅有的特性,但是我们在 Vue 3 版本也使用了 Object.defineProperty 来支持 IE 浏览器。两者具有相同的 Surface API,但是 Proxy 版本更精简,同时提升了性能。

  let a = {
        name: "小红",
        age: 12,
        oinfo: {
            school: "大学",
            hobby: ["football", "pingpang"]
        },
    }
  function observerP(data) {
        if (!data && Object.prototype.toString.call(data) !== '[object, Object]') {
            return
        }

        Object.keys(data).forEach(key => {
            let currentItem = data[key]
            if (typeof currentItem == "object") {
                observerP(currentItem)
                data[key] = new Proxy(currentItem, {
                    set(obj, prop, value) {
                        console.log("调用了set");
                        return Reflect.set(...arguments);
                    }
                })
            } else {
                Object.defineProperty(data, key, {
                    set(value) {
                        console.log("调用了set");
                        currentItem = value
                    }
                })
            }
        })
    }
    observerP(a)

当我们a.oinfo.hobby.push(“fff”)向数组中追加数据时,依然被set函数捕获,所以说Proxy支持代理数组的变化。

是不是很简单啊?喜欢的小伙伴留言点赞关注吧!

相关文章
|
6月前
|
测试技术
用navigator.sendBeacon完成网页埋点异步请求记录用户行为,当网页关闭的时候,依然后完美完成接口请求,不会因为浏览器关闭了被中断请求。
用navigator.sendBeacon完成网页埋点异步请求记录用户行为,当网页关闭的时候,依然后完美完成接口请求,不会因为浏览器关闭了被中断请求。
|
4月前
|
JavaScript 安全 网络协议
记一次典型的网站劫持
最近接到一个朋友的求助,他的网站被封了,让我帮忙看看。网站是托管在某云平台的,云平台给出的原因是网站涉赌。这就是个最简单网站,几乎全是静态网页,没什么内容,怎么会涉赌呢?难道是云平台搞错了?
41 1
记一次典型的网站劫持
|
4月前
|
数据安全/隐私保护 iOS开发
详细步骤解析:Undetectable指纹浏览器使用IPXProxy代理IP
对于品牌来说,社交媒体已经成为寻找目标受众的丰富资源。在社交媒体平台通过评论和留言进行推广具有很高的转化率,并且推广成本较低。为了获得可观的利润,大家可能需要管理至少几个社交媒体账号,然而在一台电脑上管理多个账号会比较困难。因此使用可靠的工具成为大家的必要选择,其中Undetectable指纹浏览器和IPXProxy代理IP就是两个不错的工具。下面给大家带来Undetectable指纹浏览器配置IPXProxy代理IP的详细教程。
164 0
|
4月前
|
存储 Web App开发 JavaScript
浏览器【详解】Cookie(含Cookie的起源,属性,个数和大小限制,作用,优点,缺点,JS 的操作方法等)
浏览器【详解】Cookie(含Cookie的起源,属性,个数和大小限制,作用,优点,缺点,JS 的操作方法等)
205 0
|
5月前
|
安全 前端开发 测试技术
安全开发-PHP应用&模版引用&Smarty渲染&MVC模型&数据联动&RCE安全&TP框架&路由访问&对象操作&内置过滤绕过&核心漏洞
安全开发-PHP应用&模版引用&Smarty渲染&MVC模型&数据联动&RCE安全&TP框架&路由访问&对象操作&内置过滤绕过&核心漏洞
|
6月前
使用代理IP访问隐私数据的方法探讨
使用代理IP访问隐私数据的方法探讨
为什么用代理ip网页加载不出来,一直转圈?
为什么用代理ip网页加载不出来,一直转圈?
|
前端开发
前端学习案例2-数据劫持2proxy
前端学习案例2-数据劫持2proxy
71 0
前端学习案例2-数据劫持2proxy
|
前端开发
前端学习案例1-数据劫持1
前端学习案例1-数据劫持1
72 0
前端学习案例1-数据劫持1
|
JavaScript 搜索推荐 应用服务中间件
怎么防止网站被别人使用iframe框架恶意调用
发生歹意网站的危害关于新站来说,是比较大的。那我们应该怎样防止别人歹意镜像我们的网站呢?首要得了解一下镜像网站的原理,镜像网站大约需求以下的几个条件:你的网站运用了独立IP.当然,独立ip对一个网站来说,是好的,可以和其他网站差异开来,成为镜像网站的条件之一,只是独立ip的一个小缺陷。
141 0
怎么防止网站被别人使用iframe框架恶意调用