资讯专栏INFORMATION COLUMN

【ES6入门10】:Proxy和Reflect

Jokcy / 1068人阅读

摘要:代理原始对象,或者真实数据,可以理解为供应商代理对象,可以理解为代理商,对用户来说,直接操作,而不能直接操作拦截对象属性的读取拦截对象设置属性只让用户修改属性,其他的不允许修改拦截操作只暴露属性,其他的都不暴露拦截属性名以下划线开头的,

Proxy代理
{
    // 原始对象,或者真实数据,可以理解为供应商
    let obj = {
        time: "2018-10-05",
        name: "lucy",
        age: 16,
        _is: true
    };

    // 代理对象,可以理解为代理商,对用户来说,直接操作monitor,而不能直接操作obj
    let monitor = new Proxy(obj, {
        // 拦截对象属性的读取
        get(target, key) {
            return target[key].replace("2018", "2019");
        },
        // 拦截对象设置属性
        set(target, key, value) {
            // 只让用户修改name属性,其他的不允许修改
            if (key === "name") {
                return target[key] = value;
            } else {
                return target[key];
            }
        },
        // 拦截 key in object 操作
        has(target, key) {
            // 只暴露name属性,其他的都不暴露
            if (key === "name") {
                return target[key];
            } else {
                return false;
            }
        },
        // 拦截delete
        deleteProperty(target, key) {
            // 属性名以_下划线开头的,就允许删除,否则不允许删除
            if (key.indexOf("_") > -1) {
                delete target[key];
                return true;
            } else {
                return target[key];
            }
        },
        // 拦截Object.keys Object.getOwnPropertySymbols, Object.getOwnPropertyNames
        ownKeys(target) {
            // 拦截了time属性
            return Object.keys(target).filter(item => item != "time");
        }
    });

    console.log("get", monitor.time); // 2019-10-05

    monitor.time = "2020";
    monitor.name = "can";
    console.log("set", monitor.time, monitor.name); // 2019-10-05 can

    console.log("has", "name" in monitor, "time" in monitor); // true false

    delete monitor.time;
    delete monitor._is;
    console.log(monitor); // Proxy {time: "2018-10-05", name: "can", age: 16}

    console.log("ownKeys", Object.keys(monitor)) // ["name", "age"]
}
Reflect反射

反射的是 object,Reflect的方法跟Proxy一样,都有get,set,has...

{
    let obj = {
        time: "2018-10-05",
        name: "ahhh",
        age: 16,
        _is: true
    };
    console.log(Reflect.get(obj, "time")); // 2018-10-05
    Reflect.set(obj, "name", "lxc");
    console.log(obj); // {time: "2018-10-05", name: "lxc", age: 16, _is: true}
    console.log(Reflect.has(obj, "name")); // true
}
数据校验例子
{
    function validator(target, validator) {
        return new Proxy(target, {
            _validator: validator,
            // 对set进行拦截
            set(target, key, value, proxy) {
                if (target.hasOwnProperty(key)) {
                    let va = this._validator[key]; // 拿到_validator配置好的方法
                    if (!!va(value)) {
                        // 允许修改
                        return Reflect.set(target, key, value, proxy);
                    } else {
                        // 抛出异常
                        throw Error(`不能设置${key}到${value}`);
                    }
                } else {
                    throw Error(`${key} 不存在`);
                }
            }
        });
    }

    const personValidators = {
        name(val) {
            // 如果name设置为字符串,则允许修改,否则抛出异常
            return typeof val === "string";
        },
        age(val) {
            // 如果age设置为数值类型并且大于18,则允许修改,否则抛出异常
            return typeof val === "number" && val > 18;
        }
    };

    class Person {
        constructor(name, age) {
            this.name = name;
            this.age = age;
            // 返回了一个Proxy对象,用户操作的并不是Person这个实例,而是这个实例的代理对象
            return validator(this, personValidators);
        }
    }

    const person = new Person("haha", 18);
    console.log(person); // Proxy {name: "haha", age: 18}

    // person.name = 46; // 不能设置name到46
    // person.age = 20; // 不能设置age到12
    // person.number = 111; // number 不存在

    person.name = "yoyo";
    person.age = 20;
    console.log(person); // Proxy {name: "yoyo", age: 20}
}

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/98714.html

相关文章

  • 【资源集合】 ES6 元编程(Proxy & Reflect & Symbol)

    摘要:理解元编程和是属于元编程范畴的,能介入的对象底层操作进行的过程中,并加以影响。元编程中的元的概念可以理解为程序本身。中,便是两个可以用来进行元编程的特性。在之后,标准引入了,从而提供比较完善的元编程能力。 导读 几年前 ES6 刚出来的时候接触过 元编程(Metaprogramming)的概念,不过当时还没有深究。今天在应用和学习中不断接触到这概念,比如 mobx 5 中就用到了 Pr...

    aikin 评论0 收藏0
  • ECMAScript 6入门ProxyReflect(上)

    摘要:与学习的新语法糖既能学习到新东西,又能使得自己的代码更加优雅,逼格更高,爽与之间的运用就是对对象的操作触发的拦截是对对象进行代理,通过生成的对象间接操作原本对象,最常见的就是与语法形式是需要操作的对象,而是包含操作对象的一些方法的对象是能够 Proxy与Reflect 学习es6的新语法糖既能学习到新东西,又能使得自己的代码更加优雅,逼格更高,爽proxy与Reflect之间的运用就是...

    DevTTL 评论0 收藏0
  • ES6】改变 JS 内置行为的代理与反射

    摘要:通过对这些底层内置对象的代理陷阱和反射函数,让开发者能进一步接近引擎的能力。显然,与要求代理目标对象必须是一个函数,这两个代理陷阱在函数的执行方式上开启了很多的可能性,结合使用就可以完全控制任意的代理目标函数的行为。 代理(Proxy)可以拦截并改变 JS 引擎的底层操作,如数据读取、属性定义、函数构造等一系列操作。ES6 通过对这些底层内置对象的代理陷阱和反射函数,让开发者能进一步接...

    lushan 评论0 收藏0
  • ES6重新认识JavaScript设计模式(五): 代理模式Proxy

    摘要:此时,链家起到的作用就是代理的作用。验证代理构造函数第二个参数中的方法,可以很方便的验证向一个对象的传值。 1 什么是代理模式 showImg(https://segmentfault.com/img/remote/1460000015800706?w=1262&h=464); 为其他对象提供一种代理以控制对这个对象的访问。在某些情况下,一个对象不适合或者不能直接引用另一个对象,而代理...

    verano 评论0 收藏0
  • 《深入理解ES6》笔记——代理(Proxy反射(Reflection)API(12)

    摘要:方法与代理处理程序的方法相同。使用给目标函数传入指定的参数。当然,不用反射也可以读取的值。的例子我们可以理解成是拦截了方法,然后传入参数,将返回值赋值给,这样我们就能在需要读取这个返回值的时候调用。这种代理模式和的代理有异曲同工之妙。 反射 Reflect 当你见到一个新的API,不明白的时候,就在浏览器打印出来看看它的样子。 showImg(https://segmentfault....

    ZHAO_ 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<