<
>

JavaScript 对象管家 Proxy

2023-03-11 09:02:54 来源:易采站长站 作者:

目录
正文语法对象方法属性获取器/设置器函数方法捕捉器getset应用场景验证和过滤缓存监听属性变化防止误操作虚拟化总结

正文

JavaScript>Proxy,它可以用来代理另一个对象,并可以在代理过程中拦截、覆盖和定制对象的操作。Proxy 对象封装另一个对象并充当中间人,其提供了一个捕捉器函数,可以在代理对象上拦截所有的操作,包括访问属性、赋值属性、函数调用等等。通过拦截这些操作,可以对代理对象进行定制和控制。

在开始介绍 Proxy 对象前先了解 3 个术语:

    target 目标对象:要代理的对象或函数。handler 处理程序:对代理的对象或函数执行某些操作的函数。traps 捕捉器:这些是一些用于处理目标的函数。单击此处阅读有关陷阱的更多信息。

    语法

    Proxy>

    new Proxy(target, handler);
    

    其中,target 是被代理的目标对象,handler 是一个对象,它包含了一些捕捉器函数,用来拦截代理对象的操作。

    下面是一些常见的拦截操作和对应的捕捉器函数:

    对象方法

      getPrototypeOf()Object.getPrototypeOf>setPrototypeOf()Object.setPrototypeOf 方法的捕捉器。isExtensible()Object.isExtensible 方法的捕捉器。preventExtensions()Object.preventExtensions 方法的捕捉器。getOwnPropertyDescriptor()Object.getOwnPropertyDescriptor 方法的捕捉器。handler.defineProperty()Object.defineProperty 方法的捕捉器。

      属性获取器/设置器

        get(target,>:拦截对象的读取属性操作,返回属性值。set(target, propKey, value, receiver):拦截对象的设置属性操作,返回一个布尔值表示是否设置成功。has(target, propKey):拦截对象的 in 操作符,返回一个布尔值表示对象是否包含该属性。deleteProperty(target, propKey):拦截对象的 delete 操作符,返回一个布尔值表示是否删除成功。ownKeys()Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器

        函数方法

        如果目标对象是一个函数,可以使用下面>

          apply(target, thisArg, args):拦截函数的调用操作,返回调用结果。construct(target, args, newTarget):拦截 new 操作符,返回一个对象。

          Proxy 在目标对象周围创建一个不可检测的屏障,将所有操作重定向到处理程序对象。如果发送一个空的 handler ,代理只是原始对象的一个空包装器。

          const author = {
              name: "Quintion",
              age: 36,
          };
          const proxyAuthor = new Proxy(author, {});
          console.log(author.name); // Quintion
          console.log(proxyAuthor.name); // Quintion
          

          为了赋予代理意义,需要向处理程序添加一些操作方法。

          捕捉器

          每当与一个对象交互时,都在调用一个内部方法。代理允许使用捕捉器拦截给定内部方法的执行。

          因此,当运行>author.name 时,告诉 JavaScript 引擎调用内部 [[GET]] 方法来检索 name 属性。当运行 proxyAuthor.name 时,get 捕捉器会调用处理程序中定义的 get() 函数来执行,然后再将调用发送到原始对象。

          get

          get()>

            target — 传递给代理的对象。property — 访问的属性的名称。

            要自定义代理,在处理程序对象上定义函数。下面定义了 get 方法来记录访问:

            const handler = {
                get(target, property) {
                    console.log(`捕捉器 GET:${property}`);
                    return target[property];
                },
            };
            

            为了让调用通过,捕捉器 get 返回 target[property]。使用方式如下:

            const author = {
                name: "Quintion",
                age: 36,
            };
            const handler = {
                get(target, property) {
                    console.log(`捕捉器 GET[${property}]`);
                    return target[property];
                },
            };
            const proxyAuthor = new Proxy(author, handler);
            console.log(proxyAuthor.name);
            

            执行后,将打印以下内容:

            捕捉器 GET[name]
            Quintion

            set

            set>set 捕捉器需要的参数如下:

              target — 传递给代理的对象。property — 将被设置的属性名或 Symbol。value — 新的属性值receiver — 最初被调用的对象。

              下面通过 set 捕捉器验证年龄值的输入:

              const handler = {
                  set(target, property, value) {
                      if (property === "age" && typeof value !== "number") {
                          throw new TypeError("年龄必须是一个数字");
                      }
                      target[property] = value;
                      return true;
                  },
              };
              

              下面尝试将错误的类型值赋值给 age ,则会抛出错误:

              const proxyAuthor = new Proxy(author, handler);
              proxyAuthor.age = "young";
              // 执行后抛出异常:throw new TypeError("年龄必须是一个数字");
              

              set() 方法应该返回一个布尔值 true 用来表示赋值成功。 在严格模式下运行,并且返回一个假值或什么都不返回,则会抛出错误。

              除了拦截对属性的读取和修改,Proxy 总共可以拦截 13 种操作。

              应用场景

              通过>Proxy 对象的特征,可以将其使用在下面这些场合:

              验证和过滤

              代理Proxy>age 属性赋值判断

              缓存

              代理Proxy>

              下面是一个基于 Proxy 的缓存库的示例:

              class Cache {
                  constructor() {
                      this.cache = new Map();
                      this.proxy = new Proxy(this, {
                          get(target, property) {
                              if (property === "get") {
                                  return (key) => {
                                      return target.cache.get(key);
                                  };
                              }
                              if (property === "set") {
                                  return (key, value) => {
                                      target.cache.set(key, value);
                                  };
                              }
                              if (property === "has") {
                                  return (key) => {
                                      return target.cache.has(key);
                                  };
                              }
                              if (property === "delete") {
                                  return (key) => {
                                      return target.cache.delete(key);
                                  };
                              }
                          },
                      });
                  }
              }
              

              在上面的代码中,定义了一个 Cache 类,该类中包含一个内部的 Map 对象用于存储缓存数据,并且定义了一个 proxy 对象作为该类的代理。

              proxy 对象的 get 方法中,根据传入的属性名返回相应的方法。如果属性名为 get,则返回一个可以获取缓存值的方法;如果属性名为 set,则返回一个可以设置缓存值的方法;如果属性名为 has,则返回一个可以判断是否存在缓存值的方法;如果属性名为 delete,则返回一个可以删除缓存值的方法。

              下面是一个使用该缓存库的示例:

              const cacheHelper = new Cache();
              cacheHelper.set("foo", "bar");
              console.log(cacheHelper.get("foo")); // "bar"
              console.log(cacheHelper.has("foo")); // true
              cacheHelper.delete("foo");
              console.log(cacheHelper.get("foo")); // undefined
              console.log(cacheHelper.has("foo")); // false
              

              在上面的代码中,创建了一个 Cache 对象,并调用其 set 方法设置缓存值,然后调用其 get 方法获取缓存值,并调用其 has 方法判断缓存值是否存在,最后调用其 delete 方法删除缓存值。

              监听属性变化

              代理Proxy用于监视对象属性的变化,并在属性发生变化时触发其他操作。如,创建一个代理来监视对象属性的变化,并在属性发生变化时更新页面上的元素。

              防止误操作

              代理Proxy用于防止误操作,如,创建一个代理来拦截对象的某些方法,并在方法调用时检查一些条件,以确保方法只在正确的上下文中调用。

              虚拟化

              代理Proxy可以用于创建虚拟化对象。如,创建一个代理对象,用于代替某个对象的真实实现,并且在实际对象执行之前,对其进行修改或拦截。

              总结

              上面介绍了如何使用代理Proxy对象来监视对象,通过使用处理程序对象中的捕捉器方法向它们添加自定义行为,提供更高级的对象操作和控制功能,从而增强代码的可读性和可维护性。

              以上就是JavaScript>

暂时禁止评论

微信扫一扫

易采站长站微信账号