es6-12 Proxy 和 Reflect

Proxy

{
    let obj = {
        time: '2019-11-08',
        name: 'Helzeo',
        _r: 858511254
    }

    let monitor = new Proxy(obj, {
        // 拦截对象属性的读取, 把要读取数据的 key 的值含有 2019 的 替换成 2020
        get(target, key) { // target 便是当前代理对象, key 是访问的 k 值
            return target[key].replace('2019', '2020')
        },
        // 拦截对象设置属性
        set(target, key, value) {
            if (key === 'name') { // key 为 name 的才允许修改
                return target[key] = value
            } else {
                return target[key]
            }
        },
        // 判断当前对象是否拥有某个属性 (拦截 key in Object 操作)
        has(target, key) {
            if (key === 'name') {
                return target[key]
            } else {
                return
            }
        },
        // 代理拦截删除 (拦截 delete key 操作)
        deleteProperty(target, key) {
            if (key.indexOf('_') > -1) {
                delete target[key]
                return true
            } else {
                return target[key]
            }
        },
        // 拦截遍历 (Object.keys, Object.getOwnPropertySymbol, Object.getOwnPropertyNames)
        ownKeys(target) {
            return Object.keys(target).filter(item => item != 'time')
        }
    })
    console.log(monitor.time) // 2020-11-08

    monitor.time = '2021'
    monitor.name = 'HelzeoLee'
    console.log(monitor.time) // 2020-11-08
    console.log(monitor.name) // HelzeoLee

    console.log('_r' in monitor) // false 被拦截
    console.log('name' in monitor) // true 开放拦截

    delete monitor.time
    delete monitor._r
    console.log(monitor) // {time: "2019-11-08", name: "HelzeoLee"} _r被删掉了

    console.log('ownKeys', Object.keys(monitor)) // ["name"] _r 被删除了, time 被保护了
}

Reflect

reflect 直接使用, 不需要 new, reflect 的使用和 proxy 几乎一样

{
    let obj = {
        time: '2019-11-08',
        name: 'Helzeo',
        _r: 858511254
    }

    //
    console.log(Reflect.get(obj, 'time')) // 2019-11-08

    //
    Reflect.set(obj, name, 'HelzeoLee')
    console.log(obj.name) // HelzeoLee

    // 检测属性
    console.log(Reflect.has(obj, name)) // true
}

使用场景-Proxy 和 Reflect 实现表单验证(和业务解耦)

{
    function validator(target, validator) {
        return new Proxy(target, {
            _validator: validator,
            set(target, key, value, proxy) {
                if (target.hasOwnProperty(key)) {
                    let va = this._validator[key]
                    if (va(value)) {
                        return Reflect.set(target, key, value, proxy)
                    } else {
                        throw Error(`不能设置${key}为${value}`)
                    }
                } else {
                    throw Error(`${key}, 是不存在的`)
                }
            }
        })
    }

    // 设置校验条件
    const personValidators = {
        name(val) {
            return typeof val === 'string'
        },
        age(val) {
            return typeof 'number' && val > 18
        }
    }

    class Person {
        constructor(name, age){
            this.name = name
            this.age = age
            return validator(this, personValidators)
        }
    }

    const person = new Person('Helzeo', 30)
    console.log(person)
    person.name = 55 // 报错
    console.log(person)
}
以上代码的好处就是条件和业务本身完全隔离开, 便于维护, 代码简洁, 可维护性复用性强
原文地址:https://www.cnblogs.com/helzeo/p/11821288.html