在 Javascript 中,代理使您能够捕获特定对象操作并自定义它们。代理充当对象和“现实世界”之间的中介。因此,您可以增强对象的基本操作以实现更复杂的逻辑或重新定义基本操作以满足您的需求。
用例包括:
Proxy 有两个参数:
const target = { greeting1: "Hello", greeting2: "Good morning" } const handler = { get(target, prop, receiver) { return target[prop] " friends!" } } const proxy = new Proxy(target, handler) console.log(proxy.greeting1) // Hello friends! console.log(proxy.greeting2) // Good morning friends!
在这个例子中,我们定义了一个Proxy。目标对象有两个属性。我们定义一个提供 get() 处理程序实现的处理程序。 get 陷阱拦截对目标对象上任何属性的访问,在其中,我们可以根据需要修改行为。
通过这种设置,这意味着每次我们要访问目标对象中的属性时,处理程序都会拦截它,并运行我们实现的代码。在我们的例子中,它只获取属性值并添加好友!.
代理通常与 Reflect API 一起使用。 Reflect 提供与代理陷阱同名的方法。正如其名称所示,它反映了调用相应对象内部方法的语义。
const target = { greeting1: "Hello", greeting2: "Good morning" } const handler = { get(target, prop, receiver) { return Reflect.get(...arguments) " friends!" } } const proxy = new Proxy(target, handler) console.log(proxy.greeting1) // Hello friends! console.log(proxy.greeting2) // Good morning friends!
Reflect 不需要使用代理,但使用 Reflect 可以让我们确保行为与本机 Javascript 引擎操作相匹配。它还确保与未来更新的兼容性,防止意外的副作用并简化代码。如果没有它,开发人员将不得不重新实现属性访问、赋值、删除等行为……这可能容易出错并且与 Javascript 的本机行为不一致。
让我们构建一些示例来探索我们可以使用 Proxy 做什么。
在我们的第一个示例中,假设我们希望记录对对象执行的操作。每当我们获取、设置或删除一个属性时,我都想打印到控制台。这对于调试目的可能很有用。
const target = { name: "Damien", age: 32, status: "WRITING" } const loggerHandler = { get(target, prop, receiver) { if (prop in target) { console.log(`[LOG] Accessing property ${prop}. Current value is ${target[prop]}`) return Reflect.get(...arguments) } else { console.error(`[LOG] Error accessing non-existent property ${prop}`) } }, set(target, key, value) { console.log(`[LOG] Setting property ${key}. New value: ${value}`) return Reflect.set(...arguments) }, deleteProperty(target, prop) { console.warn(`[LOG] Deleting property: ${prop}`) return Reflect.deleteProperty(...arguments) } } const proxy = new Proxy(target, loggerHandler) proxy.name // [LOG] Accessing property name. Current value is Damien proxy.status // [LOG] Accessing property status. Current value is WRITING proxy.name = "Bob" // [LOG] Setting property name. New value: Bob proxy.status = "NAPPING" // [LOG] Setting property status. New value: NAPPING proxy.job = "Developer" // [LOG] Setting property job. New value: Developer delete proxy.job // [LOG] Deleting property: job proxy.job // [LOG] Error accessing non-existent property job
我们定义了一个loggerHandler,它重新定义了3个基本操作:获取、设置和删除。对于每个操作,我们都会将一些内容记录到控制台,描述正在发生的情况。 Proxy 的美妙之处在于,我们不需要每次都编写控制台语句。我们像往常一样与对象交互,代理负责记录日志行为。很酷不是吗?
在我们的第二个示例中,我们将使用代理来执行表单数据的输入验证。
const validationRules = { name: value => value.length >= 3 || "Name must be at least 3 characters long", age: value => Number.isInteger(value) || "Age must be a number", email: value => value.includes('@') || "Enter a valid email" } let formData = { name: "", age: null, email: "" } const formHandler = { set(target, key, value) { if (typeof value === "string") { value = value.trim() } const validationResult = validationRules[key](value) if (validationResult !== true) { console.error(`Validation failed for property ${key}: ${validationResult}`) return false; } return Reflect.set(...arguments) } } const formProxy = new Proxy(formData, formHandler) formProxy.age = "32 years old" // Validation failed for property age: Age must be a number formProxy.name = "Da" // Validation failed for property name: Name must be at least 3 characters long formProxy.email = "damcoss mail.com" // Validation failed for property email: Enter a valid email formProxy.age = 32 // OK formProxy.name = "Damien" // OK formProxy.email = "[email protected]" // OK
我们在这里定义一个具有不同方法的对象,用于验证值是否有效。然后,我们使用相同的逻辑。我们有要代理的目标对象 formData。在 formHandler 中,我们重新定义 set() 方法以将验证规则应用于输入值。
代理与 Reflect API 相结合,是拦截和自定义对象操作的灵活而强大的工具。使用它们,您可以动态增强和控制行为。通过使用 Reflect API,您还可以确保行为与 Javascript 引擎一致。
代理通常在库和框架中使用,以实现高级行为,例如反应式编程、API 包装器和属性观察。
玩得开心❤️
免责声明: 提供的所有资源部分来自互联网,如果有侵犯您的版权或其他权益,请说明详细缘由并提供版权或权益证明然后发到邮箱:[email protected] 我们会第一时间内为您处理。
Copyright© 2022 湘ICP备2022001581号-3