ES6——代理与反射

一、Reflect

1.Reflect是什么

Reflect是一个内置的JS对象,它提供了一系列方法,可以让开发者通过调用这些方法,访问一些JS底层功能。
由于它类似于其他语言的反射,因此取名为Reflect。

2.可以做什么

使用Reflect可以实现诸如 属性的赋值与取值、调用普通函数、调用构造函数、判断属性是否存在与对象中 等等功能。
有一个重要的理念,在ES5就被提出:减少魔法、让代码更加纯粹
这种理念很大程度上是受到函数式编程的影响

ES6进一步贯彻了这种理念,它认为,对属性内存的控制、原型链的修改、函数的调用等等,这些都属于底层实现,属于一种魔法,因此,需要将它们提取出来,形成一个正常的API,并高度聚合到某个对象中,于是,就造就了Reflect对象。

因此,你可以看到Reflect对象中有很多的API都可以使用过去的某种语法或其他API实现。

3.API

  1. Reflect.set(target, propertyKey, value): 设置对象target的属性propertyKey的值为value,等同于给对象的属性赋值
  2. Reflect.get(target, propertyKey): 读取对象target的属性propertyKey,等同于读取对象的属性值
  3. Reflect.apply(target, thisArgument, argumentsList):调用一个指定的函数,并绑定this和参数列表。等同于函数调用
  4. Reflect.deleteProperty(target, propertyKey):删除一个对象的属性
  5. Reflect.defineProperty(target, propertyKey, attributes):类似于Object.defineProperty,不同的是如果配置出现问题,返回false而不是报错
  6. Reflect.construct(target, argumentsList):用构造函数的方式创建一个对象
  7. Reflect.has(target, propertyKey): 判断一个对象是否拥有一个属性
    其他API:https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
    这里只是通过实例展示Reflect概念
const obj = {
    a: 1,
    b: 2
};
Reflect.set(obj, "a", 10);
//等效于
// obj.a = 10;
console.log(Reflect.get(obj, "a"));
//等效于
//console.log(obj.a);
function method(a, b){
    console.log("method", a, b);
};
Reflect.apply(method, null, [3, 4]);
//等效于
// method(3, 4);

const obj = {
    a: 1,
    b: 2
};
Reflect.deleteProperty(obj, "a");
//等效于
// delete obj.a;

二、Proxy代理

代理:提供了修改底层实现的方式,代理不占空间

//代理一个目标对象
//target:目标对象
//handler:是一个普通对象,其中可以重写底层实现
//返回一个代理对象
new Proxy(target, handler)
const obj = {
    a: 1,
    b: 2
};
const proxy = new Proxy(obj, {
    set(target, propertyKey, value) {
        // console.log(target, propertyKey, value);
        // target[propertyKey] = value;//原来的设置值
        Reflect.set(target, propertyKey, value);//利用反射
    },
    get(target, propertyKey) {
        if (Reflect.has(target, propertyKey)) {
            return Reflect.get(target, propertyKey);
        } else {
            return -1;
        };
    },
    has(target, propertyKey) {
        return false;
    }
});
console.log(proxy);
proxy.a = 10;
console.log(proxy.a);
console.log(proxy.d);//不存在返回-1
console.log("a" in proxy);

三、应用-观察者

有一个对象,是观察者,它用于观察另外一个对象的属性值变化,当属性值变化后会收到一个通知,可能会做一些事。

<div id="container"></div>
<script>
    //创建一个观察者
    function observer(target) {
        const div = document.getElementById("container");
        const ob = {};
        const props = Object.keys(target);//遍历参数属性
        for (const prop of props) {
            Object.defineProperty(ob, prop, {
                get() {
                    return target[prop];
                },
                set(val) {
                    target[prop] = val;
                    render();
                },
                enumerable: true//可遍历
            })
        }
        render();
        function render() {
            let html = "";
            for (const prop of Object.keys(ob)) {
                html += `
                    <p><span>${prop}:</span><span>${ob[prop]}</span></p>
                `;
            }
            div.innerHTML = html;
        }
        return ob;
    }
    const target = {
        a: 1,
        b: 3
    };
    const obj = observer(target);//执行后target再添加键值将无法实时监控
</script>

利用代理与反射优化

<div id="container"></div>
<script>
    //创建一个观察者
    function observer(target) {
        const div = document.getElementById("container");
        const proxy = new Proxy(target, {
            set(target, prop, value) {
                Reflect.set(target, prop, value);//可以从底层监控新增的数据
                render();
            },
            get(target, prop){
                return Reflect.get(target, prop);
            }
        })
        render();
        function render() {
            let html = "";
            for (const prop of Object.keys(target)) {
                html += `
                    <p><span>${prop}:</span><span>${target[prop]}</span></p>
                `;
            }
            div.innerHTML = html;
        }
        return proxy;
    };
    const target = {
        a: 1,
        b: 2
    };
    const obj = observer(target);
</script>

四、应用-'简化’构造函数

class User {

};
function ConstructorProxy(Class, ...propNames) {
    return new Proxy(Class, {
        construct(target, argumentsList) {
            const obj = Reflect.construct(target, argumentsList)
            propNames.forEach((name, i) => {
                obj[name] = argumentsList[i];
            })
            return obj;
        }
    })
};
const UserProxy = ConstructorProxy(User, "firstName", "lastName", "age");
const obj = new UserProxy("小", "李", 18);
console.log(obj);


class Monster {

};
const MonsterProxy = ConstructorProxy(Monster, "attack", "defence", "hp", "rate", "name")
const m = new MonsterProxy(10, 20, 100, 30, "小怪");
console.log(m);

在这里插入图片描述

五、应用-可验证函数

function sum(a, b) {
    return a + b;
};
function proxyFunction(func,...argus){
    const proxy = new Proxy(func,{
        apply(target,thisArgument,argumentsList){
            argus.forEach((t,i)=>{
                const arg = argumentsList[i];
                if(typeof arg !==t){
                    throw new Error('参数类型不达标!');
                }
            });
            return Reflect.apply(target, thisArgument, argumentsList);
        }
    })
    return proxy;
};
const sumProxy = proxyFunction(sum, "number", "number");
console.log(sumProxy(1, 2));
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞羽逐星

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值