JavaScript中的数据劫持

399 阅读1分钟

数据劫持

什么是数据劫持

将原始数据 劫持出一份一摸一样, 听起来有点像 浅拷贝

劫持出来的数据, 默认是不可以修改的

语法: Object.defineProperty(那个对象, '对象的key', {配置项})

配置项:

  1. value 访问这个值 之后, 得到结果

  2. writable 决定当前这个属性能否被修改, 默认是 false

  3. enumerable 决定当前这个属性能否被枚举, 决定当前这个属性能否被遍历到

  4. getter 是一个函数, 是一个获取器, 当访问这个属性时, 会执行这个函数 + getter 不能和 value writable 一起使用

  5. setter 是一个函数, 是一个设置器, 当设置这个属性是, 会执行这个函数

  const obj = {}
       obj.name = 'QF666'
       console.log(obj)

       // let str = 'age'
       // Object.defineProperty(obj, str, {配置项})
       Object.defineProperty(obj, 'age', {
           // value: 'QF999',
           // writable: true,
           enumerable: true,
           get() {
               // console.log('你当前访问了 这个 age 属性, 触发了 get 函数')
               return 'qwer'
           },
           set(val) {
               console.log('你当前想要修改这个 age 属性, 修改的值 是: ', val)
           }
       })
       // console.log(obj)
       // for (let k in obj) {
       //     console.log(k)
       // }
       console.log(obj.age)

       obj.age = 100

实现数据劫持

<body>
    <div id="box"></div>
    <script>
        // 实现数据劫持
        const box = document.querySelector('#box')
        const obj = {
            name: 'QF666',
            age: 18
        }
        console.log('原始对象obj:', obj)
        const res = {}

        Object.defineProperty(res, 'name', {
            get() {
                return obj.name
            },
            set(val) {
                // console.log('你想要修改这个属性的值, 新值为: ', val)
                obj.name = val
                box.innerHTML = `名字: ${res.name}; 年龄: ${res.age}`
            }
        })

        Object.defineProperty(res, 'age', {
            get() {
                return obj.age
            },
            set(val) {
                // console.log('你想要修改这个属性的值, 新值为: ', val)
                obj.age = val
                box.innerHTML = `名字: ${res.name}; 年龄: ${res.age}`
            }
        })

        // console.log('数据劫持后的 res: ', res)
        // console.log(res.name)
        // console.log(res.age)

        // res.name = 'QF999'
        // res.age = 99
        // console.log(res.name)

        box.innerHTML = `名字: ${res.name}; 年龄: ${res.age}`

        res.age = 99


    </script>
</body>

封装数据劫持

<body>
    <input type="text" name="" id="inp">
    <div id="box"></div>
    //封装数据劫持
    <script>
        const box = document.querySelector('#box')
        const obj = {
            name: 'QF666',
            age: 18
        }
        function observer(origin, callback) {
            const target = {}

            for (let k in origin) {
                Object.defineProperty(target, k, {
                    get() {
                        return origin[k]
                    },
                    set(val) {
                        // console.log('你现在想要修改的key是' , k, '修改的值为', val)
                        origin[k] = val
                        callback(target)
                    }
                })
            }

            callback(target)
            return target
        }

    </script>
    
    //调用数据劫持
    <script>

        function fn(res) {
            box.innerHTML = `名字: ${res.name}; 年龄: ${res.age}`
        }

        const app = observer(obj, fn)


        document.querySelector('#inp').oninput = function (e) {
            app.age = e.target.value
        }
    </script>
</body>