// 操作对象的 API---Proxy(代理)。
// 什么是 Proxy
// 在JavaScript中,Proxy是一种允许你创建一个对象的代理,可以用来拦截并定义基本操作的行为的对象。这在很多场景下都非常有用,比如数据绑定、属性访问控制、日志记录等。
// Proxy可以让你在访问某个对象的属性、方法或进行其他操作时,先执行自定义的逻辑。
// 允许对来访人员进行改造(提供一种机制:可以对外界的访问进行过滤和改写)。
// 应用场景
// 数据绑定:在前端框架中,可以使用Proxy来监听对象属性的变化,自动更新UI。
// 权限控制:可以通过Proxy来控制对对象属性的访问权限,实现私有属性或方法。
// 日志记录:在访问特定属性或方法前后记录日志,便于调试和监控。
// 性能监控:监控对象的操作,收集性能数据。
// API增强:在不修改原有对象的基础上,增加额外的功能或修改现有功能的行为。
// API指应用程序编程接口,可以通过这个接口,访问到自己后端写好的属性和方法,或者数据。
// 用 Proxy 创建代理需要传入两个参数:目标对象(target)和处理程序(handler)。语法格式如下:
// var proxy = new Proxy(target, handler);
// 参数说明如下:
// target:要拦截的目标对象。
// handler:制定拦截行为的对象。
// 我们来写段代码验证一下
let target = { name: '张三', age: 18 };
let proxy = new Proxy(target, {});
// 拦截对象为target,拦截行为为 {},也就是啥都不做。
proxy.name = "闷墩儿";
console.log(proxy.name);
console.log(target.name);
target.name = "憨憨";
console.log(proxy.name);
console.log(target.name);
// proxy 的所有操作都转发给了 target 对象,当在 proxy 上创建了 name 属性之后,
// 相应的 target 上也会创建 name 属性。由于 target.name 和 proxy.name 都是引用的 target.name,
// 所以当修改了 target.name 的值后,proxy.name 的值也会修改。
// Proxy 的代理拦截方法如下表所示:
// 拦截方法 方法说明
// get(target, propKey, receiver) 拦截对象属性的读取。
// set(target, propKey, value, receiver) 拦截对象属性的设置。
// has(target, propKey) 拦截 propKey in proxy 的操作。
// deleteProperty(target, propKey) 拦截 delete proxy[propKey]的操作。
// ownKeys(target) 拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in 循环,返回一个数组。
// getOwnPropertyDescriptor(target, propKey) 拦截 Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。
// defineProperty(target, propKey, propDesc) 拦截 Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。
// preventExtensions(target) 拦截 Object.preventExtensions(proxy),返回一个布尔值。
// getPrototypeOf(target) 拦截 Object.getPrototypeOf(proxy),返回一个对象。
// isExtensible(target) 拦截 Object.isExtensible(proxy),返回一个布尔值。
// setPrototypeOf(target, proto) 拦截 Object.setPrototypeOf(proxy, proto),返回一个布尔值。
// apply(target, object, args) 拦截 Proxy 实例作为函数调用的操作。
// construct(target, args) 拦截 Proxy 实例作为构造函数调用的操作。
// 如此多的拦截操作方法!在本文中我们就不一一举例了,只给大家介绍最常用的四种拦截方法:
// get(target, propKey, receiver)
// 该方法接受三个参数,具体说明如下:
// target:被读取属性的目标对象。
// propKey:要读取的属性键值。
// receiver:操作发生的对象。
// 示例代码
// let dog = {
// name: "闷墩儿",
// };
// var proxy = new Proxy(dog, {
// get(target, propKey) {
// // 遍历目标对象的属性键值
// if (propKey in target) {
// return target[propKey]; // 返回相应的属性值
// } else {
// throw new ReferenceError(propKey + " 属性不存在");
// }
// },
// });
// console.log("访问 dog 对象中的 name 属性值为:" + proxy.name);
// console.log("访问不存在的 age 属性:" + proxy.age);
// 访问 dog 对象中的 name 属性值为:张三
// 访问不存在的 age 属性:ReferenceError: age 属性不存在
// set(target, propKey, value, receiver)
// 如果要创建一个只接受数字作为属性值的对象,那么在创建属性时,必须判断该值是否是数字,若不是数字应该报错。我们使用 set 方法就可以实现这个需求。
// set 方法接受四个参数,具体说明如下:
// target:用于接收属性的目标对象。
// propKey:要写入的属性键值。
// value:要写入的属性值。
// receiver:操作发生的对象。
// let validator = {
// set(target, propKey, value) {
// if (propKey === "age") {
// // 判断 age 属性值是否是数字
// if (!Number.isInteger(value)) {
// throw new TypeError("狗狗的年龄只能是整型哦!");
// }
// }
// target[propKey] = value;
// return true;
// },
// };
// let dog = new Proxy({}, validator);
// console.log((dog.age = "22"));
// 从控制台的输出结果可以看出,当 age 属性值设为字符串时,抛出错误。
// has(target, propKey)
// has 方法接收两个参数,具体说明如下:
// target:读取属性的目标对象。
// propKey:要检查的属性键值。
// let dog = {
// name: "闷墩儿",
// age: 2,
// };
// let handler = {
// has(target, propKey) {
// if (propKey == "age" && target[propKey] < 5) {
// console.log(`${target.name}的年龄小于 5 岁哦!`);
// return true;
// }
// },
// };
// let proxy = new Proxy(dog, handler);
// console.log("age" in proxy);
// ownKeys(target)
// ownKeys 方法用于拦截对象自身属性的读取操作,具体可以拦截以下四种操作:
// Object.getOwnPropertyNames()
// Object.getOwnPropertySymbols()
// Object.keys()
// for...in
// let dog = {
// name: "闷墩儿",
// age: 2,
// food: "狗罐头",
// };
// const proxy = new Proxy(dog, {
// ownKeys() {
// return ["name", "color"];
// },
// });
// for (let key in proxy) {
// console.log(key); // 输出 name
// }
// 只输出了 name 属性,这是因为在 dog 对象中不包含 color 属性。
//为避免冲突我注释了一些代码,如果想要看展示效果直接取消注释就可以了
//下周更一更vue3
一起来学javascript-proxy
于 2024-06-13 16:06:23 首次发布