这篇文章主要介绍“JavaScript对象管家Proxy怎么使用”,在日常操作中,相信很多人在JavaScript对象管家Proxy怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”JavaScript对象管家Proxy怎么使用”的疑惑有所帮助!接下来,请跟着小编一起来学习吧!
JavaScript 在 ES6 中,引入了一个新的对象类型
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, propKey, receiver):拦截对象的读取属性操作,返回属性值。
set(target, propKey, value, receiver):拦截对象的设置属性操作,返回一个布尔值表示是否设置成功。
has(target, propKey):拦截对象的
in操作符,返回一个布尔值表示对象是否包含该属性。
deleteProperty(target, propKey):拦截对象的
delete操作符,返回一个布尔值表示是否删除成功。
ownKeys():
Object.getOwnPropertyNames方法和
Object.getOwnPropertySymbols方法的捕捉器
函数方法
如果目标对象是一个函数,可以使用下面 2 个捕捉器。
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可以用于创建虚拟化对象。如,创建一个代理对象,用于代替某个对象的真实实现,并且在实际对象执行之前,对其进行修改或拦截。