ES6学习之路(六) Proxy 代理器&Reflect

JS Proxy与Reflect详解
本文详细介绍了JavaScript中Proxy和Reflect的使用方法与应用场景。通过示例展示了如何利用Proxy拦截目标对象的操作,并解释了Reflect提供的统一操作接口。适用于希望深入了解这两种机制的开发者。

Proxy 代理器

用户必须通过它来操作原对象;

    var proxy = new Proxy(target,handler);
    //target参数表示所要拦截的目标对象,
    //handler参数也是一个对象,用来定制拦截行为。

    var p1 = new Proxy({},{
        get:function(target,property){
            return 35;
        }
    });

    console.log(p1.time);//35
    console.log(p1.name);//35
    console.log(p1.title);//35

    //上面由于Proxy接收的目标对象是空,第二个参数设置配置对象进行拦截,
    //get方法的两个参数分别是目标对象和想要访问的属性,因为Proxy拦截,所以访问到的任何属性都是35;

    // 要使用Proxy起作用,就必须操作Proxy的实例,而不是针对目标对象进行操作;
//如果 handler没有进行任何设置,那就等同于直接通向源对象;
    var target = {};
    var handler = {};
    var proxy = new Proxy(target,handler);

    proxy.a = 'b';
    console.log(target.a);//'b';

    //Proxy的实例也可以作为其它对象的原型,
    var proxy = new Proxy({},{
        get : function (target,property) {
            return 35;
        }
    });
     let obj = Object.create(proxy);

     console.log(obj.time);//35
////proxy 同一个拦截函数,可拦截多个操作设置
var handler = {
        get:function(target,name){
            if(name === 'prototype'){
                return Object.prototype;
            }
            return 'Hello' + name;
        },
        apply:function(target,thisBinding,args){
            return args[0];
        },
        construct:function(target,args){
            return {value:args[1]};
        }
    };

    var fproxy = new Proxy(function(x,y){return x+y},handler);

    console.log(fproxy(1,2));//1
    console.log(new fproxy(1,2));//{value: 2}
    console.log(fproxy.prototype === Object.prototype)//true
    console.log(fproxy.foo)//Hellofoo
    ////对于可以设置、但没有设置拦截的操作,则直接落在目标对象上,按照原先的方式产生结果。

注意

虽然 Proxy 可以代理针对目标对象的访问,但它不是目标对象的透明代理,即不做任何拦截的情况下,也无法保证与目标对象的行为一致。主要原因就是在 Proxy 代理的情况下,目标对象内部的this关键字会指向 Proxy 代理。

Proxy 的方法很多,具体可以参考ES6入门点击查看

Reflect

Reflect 对象的目的
1.将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。

2.修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。

3.让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。

4.Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。

Reflect主要是继承了一些的Object的静态方法,使用起来更友好,更方便,
下面是它的方法
Reflect.apply(target,thisArg,args)
Reflect.construct(target,args)
Reflect.get(target,name,receiver)
Reflect.set(target,name,value,receiver)
Reflect.defineProperty(target,name,desc)
Reflect.deleteProperty(target,name)
Reflect.has(target,name)
Reflect.ownKeys(target)
Reflect.isExtensible(target)
Reflect.preventExtensions(target)
Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf(target, prototype)

具体链接请点击ES6入门

### JavaScript ES6 Proxy 的使用方法及示例 #### 基础概念 ProxyES6 中引入的一种机制,能够拦截并自定义对目标对象的操作行为。通过 `new Proxy()` 构造创建一个代理对象,该对象可以捕获特定的行为(如属性访问、赋值等),并对这些行为进行修改或扩展。 #### 创建基础的 Proxy 对象 以下是创建一个简单的 Proxy 对象的示例: ```javascript let targetObject = { name: "Alice", age: 25, }; let handler = { get(target, property, receiver) { console.log(`正在获取属性 ${property}`); return Reflect.get(target, property, receiver); }, set(target, property, value, receiver) { console.log(`正在设置属性 ${property} 为 ${value}`); return Reflect.set(target, property, value, receiver); } }; let proxy = new Proxy(targetObject, handler); console.log(proxy.name); // 输出:正在获取属性 name \n Alice proxy.age = 30; // 输出:正在设置属性 age 为 30 console.log(proxy.age); // 输出:正在获取属性 age \n 30 ``` 上述代码展示了如何通过 `get` 和 `set` 方法来拦截属性的读取和写入操作[^1]。 #### 高级用法 除了基本的 `get` 和 `set` 拦截外,Proxy 还支持多种其他的拦截操作,例如 `apply`, `construct`, `has`, `deleteProperty` 等。下面是一个更复杂的例子,展示如何拦截删除属性的操作: ```javascript let person = { firstName: "John", lastName: "Doe" }; let advancedHandler = { deleteProperty(target, property) { if (confirm(`确认要删除属性 "${property}" 吗?`)) { const result = Reflect.deleteProperty(target, property); if (result) { console.log(`${property} 属性已被成功删除`); } else { console.error(`无法删除属性 ${property}`); } return result; } return false; } }; let advancedProxy = new Proxy(person, advancedHandler); // 尝试删除属性 delete advancedProxy.firstName; // 浏览会弹出确认框询问是否删除 console.log(advancedProxy); // 如果删除成功,则不会显示 firstName ``` 此示例中,当尝试删除某个属性时,程序会提示用户确认删除动作,并根据用户的响应决定是否执行删除操作[^3]。 #### 使用 Proxy 作为原型对象 还可以将 Proxy 实例设为其他对象的原型,从而影响继承链上的行为。如下所示: ```javascript let prototypeProxy = new Proxy({}, { get(target, property) { return `${property} 被访问`; } }); let childObject = Object.create(prototypeProxy); console.log(childObject.time); // 输出:time 被访问 console.log(childObject.location); // 输出:location 被访问 ``` 在这个场景下,任何未定义于子对象中的属性都会触发其原型上定义的 `get` 捕获逻辑[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值