es6之proxy和reflect(二)几个运用场景

本文介绍了ES6中的Proxy和Reflect的几个实用场景,包括在观察者模式中的运用,简化构造函数,以及实现可验证的函数参数。通过Proxy,可以在不额外占用内存的情况下实现对象的动态监听和参数验证,提升代码的简洁性和效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在观察者模式上的运用

有一个对象,是观察者,它用于观察另一个对象的属性值变化,当属性值变化后会收到一个通知,可能会做一些事
没有实现代理之前的实现方式

 function observer(target) {
     const div = document.getElementById("container");
     const ob = {};
     const props = Object.keys(target);
     for (const prop of props) {
         // ob[prop] = target[prop];
         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: 2
 }
 const obj = observer(target);

这里ob和target是两个对象,浪费内存空间 另一点:
虽说用函数把两个对象进行了关联,但再关联之后target再添加属性 例如c:20则obj.c = 5,这一操作上面写法的观察者模式将无法关联到。
而用Proxy则相当于在target对象上覆盖一层,不另开辟空间,而且target后续的添加属性也会很好的关联起来:

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; //target
}
const target = {
   a: 1,
   b: 2
}
const obj = observer(target);

二 偷懒的构造函数

class User {
    constructor(firstName, lastName, age) {
        this.firstName = firstName;
        this.lastName = lastName;
        this.age = age;
    }
}


function ConstructorProxy(Class) {
    return new Proxy(Class, {
        construct(target, argumentsList) {
            console.log(argumentsList)
            return Reflect.construct(target, argumentsList)
        }
    })
}

const UserProxy = ConstructorProxy(User);
new UserProxy();

const obj = new UserProxy("袁", "进", 18);
console.log(obj);

在这里插入图片描述
这段代码实现的功能,constructor里的那些this.firstName = firstName;的语句,很多很繁琐,在一些场景下,我们可以通过Proxy在底层实现里把这一工作做了,而实现一些“偷懒”:


class User {
    // constructor(firstName, lastName, age) {
    //     this.firstName = firstName;
    //     this.lastName = lastName;
    //     this.age = age;
    // }
}


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");
new UserProxy();

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);

在这里插入图片描述

可验证的函数参数

有些场景需要验证函数的参数,这样抽离出来的验证方法,用Proxy实现如下:
求两数之后的函数,需要验证两参数是否是number类型

function sum(a, b) {
    return a + b;
}

function validatorFunction(func, ...types) {
    const proxy = new Proxy(func, {
        apply(target, thisArgument, argumentsList) {
            types.forEach((t, i) => {
                const arg = argumentsList[i];
                if (typeof arg !== t) {
                    throw new TypeError(`第${i+1}个参数${argumentsList[i]}不满足类型${t}`);
                }
            })
         return   Reflect.apply(target, thisArgument, argumentsList);
        }
    })
    return proxy;
}
const sumProxy = validatorFunction(sum, "number", "number")
console.log(sumProxy("1", "2"));

不用Proxy时,常用一个函数来实现这一功能

function validatorFunction(func, ...types) {
    return function(...argumentsList) {
        types.forEach((t, i) => {
            const arg = argumentsList[i];
            if (typeof arg !== t) {
                throw new TypeError(`第${i+1}个参数${argumentsList[i]}不满足类型${t}`);
            }
        })
        return func(...argumentList)
    }
}
const sumProxy = validatorFunction(sum, "number", "number")
console.log(sumProxy("1", "2"));

多写一个函数增加了内存开销,代理不会增加内存开销。显然Proxy实现这一功能时有很多优势。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值