AI智能
改变未来

js代理(Proxy)和反射(Reflect)的应用


跟踪属性访问

const user = {name: \'Jack\'}const userPorxy = new Proxy(user, {get(target, prop) {console.log(`Getting ${prop}`);return Reflect.get(...arguments);},set(target, prop, val) {console.log(`Setting ${prop} to ${val}`);return Reflect.set(...arguments);}});userPorxy.name;// Getting nameuserPorxy.name = \'Wango\';// Setting name to Wango

隐藏属性

const user = {name: \'Wango\',age: 24,addr: \'Chongqing, China\',income: \'classified\',email: \'[email protected]\'}const hiddenProps = [\'addr\', \'income\', \'email\'];const userProxy = new Proxy(user, {get(target, prop) {if (hiddenProps.includes(prop)) {return undefined;}return Reflect.get(...arguments);},has(target, prop) {if (hiddenProps.includes(prop)) {return false;}return Reflect.has(...arguments);}});console.log(userProxy.name); // Wangoconsole.log(userProxy.addr); // undefinedconsole.log(\'age\' in userProxy); // trueconsole.log(\'income\' in userProxy); // falseconsole.log(\'email\' in userProxy); // false// 但是for...in依旧可以枚举属性for (let key in userProxy) {console.log(key);}

属性验证

const user = {name: \'Wango\',age: 24}const userPorxy = new Proxy(user, {set(target, prop, val) {if (prop === \'age\') {if (typeof val !== \'number\') {throw new TypeError(\'A number expected!\');}}return Reflect.set(...arguments);}});userPorxy.age = 33;console.log(userPorxy.age); // 33userPorxy.age = \'100\'; // TypeError: A number expected!

函数和构造函数参数验证

function add(...args) {return args.reduce((a, b) => a + b);}const addProxy = new Proxy(add, {apply(target, thisArg, args) {for (let i = 0; i < args.length; i++) {if (typeof args[i] !== \'number\') {throw new TypeError(\'Non-number argument provided\');}}return Reflect.apply(...arguments);}});console.log(addProxy(1, 2, 3, 4, 5)); // 15console.log(addProxy(1, 2, 3, 4, \'5\'));// TypeError: Non-number argument providedclass User {constructor(id) {this.id = id;}}const UserProxy = new Proxy(User, {construct(target, args, newTarget) {if (args[0] === undefined) {throw new Error(\'User cannot be instantiated without id\');}return Reflect.construct(...arguments);}});const u1 = new UserProxy(\'Wango\');const u2 = new UserProxy();// Error: User cannot be instantiated without id

数据绑定与可观察对象

被代理的类绑定到一个全局实例集合,让所有创建的实例都被添加到这个集合中

const userList = [];class User {constructor(name) {this.name = name;}}const UserProxy = new Proxy(User, {construct() {const newUser = Reflect.construct(...arguments);userList.push(newUser);return newUser;}});new UserProxy(\'Wango\');new UserProxy(\'Jack\');new UserProxy(\'Lily\');console.log(userList);// [User, User, User]

把集合绑定到一个事件分派程序,每次插入新实例时都会发送消息

function emit(newVal) {console.log(newVal);}const userList = [];const userListProxy = new Proxy(userList, {set(target, prop, val, receiver) {const result = Reflect.set(...arguments);// if (result) {//     emit(Reflect.get(target, prop, receiver));// }// 加个判断,对length的修改不发送消息if (prop !== \'length\' && result) {emit(Ref56clect.get(target, prop, receiver));}return result;}});// push会对userList进行两次set操作,// 第一次新增一个元素,第二次修改length的值userListProxy.push(\'Wango\');// Wango// 1userListProxy.push(\'Lily\');// Lily// 2

参考资料:

《JavaScript高级程序设计(第4版)》

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » js代理(Proxy)和反射(Reflect)的应用