在 ES6 中,我们可以使用 Proxy 和 Reflect 对对象进行拦截、监视和修改。它们是 JavaScript 语言提供的一种元编程机制,可以让开发者更加灵活地控制代码的行为。本文将详细介绍 Proxy 和 Reflect 的用法及其应用。
Proxy
Proxy 是 ES6 中新增的一个特性,它可以拦截并修改对象的默认行为。它的基本用法如下:
// javascriptcn.com 代码示例 const target = {}; const proxy = new Proxy(target, { get(target, key, receiver) { console.log(`getting ${key}`); return Reflect.get(target, key, receiver); }, set(target, key, value, receiver) { console.log(`setting ${key} to ${value}`); return Reflect.set(target, key, value, receiver); }, }); proxy.foo = "bar"; // setting foo to bar console.log(proxy.foo); // getting foo, bar
在上面的代码中,我们使用 new Proxy()
创建了一个代理对象 proxy
,它拦截了 target
对象的 get
和 set
操作。当我们访问 proxy.foo
时,会触发拦截器中的 get
方法,并输出 getting foo
,最后返回 target.foo
的值。当我们给 proxy.foo
赋值时,会触发拦截器中的 set
方法,并输出 setting foo to bar
,最后将 target.foo
的值设置为 bar
。
除了上面的 get
和 set
方法,Proxy 还支持很多其他的拦截器,例如:
has(target, key)
:拦截key in target
操作,返回一个布尔值。deleteProperty(target, key)
:拦截delete target[key]
操作,返回一个布尔值。apply(target, thisArg, args)
:拦截函数调用,返回一个值。construct(target, args, newTarget)
:拦截new target(...args)
操作,返回一个对象。
Reflect
Reflect 是 ES6 中新增的一个全局对象,它提供了一些与 Proxy 相关的方法。它的基本用法如下:
const obj = {}; Reflect.set(obj, "foo", "bar"); console.log(obj.foo); // bar
在上面的代码中,我们使用 Reflect.set()
设置了 obj.foo
的值为 "bar"
,并输出了 obj.foo
的值。
除了 set
方法,Reflect 还支持很多其他的方法,例如:
get(target, key, receiver)
:获取对象的属性值。has(target, key)
:判断对象是否有某个属性。deleteProperty(target, key)
:删除对象的某个属性。apply(target, thisArg, args)
:调用函数。construct(target, args)
:创建对象实例。
应用
Proxy 和 Reflect 可以用于很多场景,例如:
数据校验
我们可以使用 Proxy 来校验数据的合法性,例如:
// javascriptcn.com 代码示例 const validator = { set(target, key, value) { if (key === "age" && typeof value !== "number") { throw new TypeError("Age must be a number."); } return Reflect.set(target, key, value); }, }; const person = new Proxy({}, validator); person.name = "John"; person.age = 30; console.log(person); // { name: 'John', age: 30 } person.age = "30"; // TypeError: Age must be a number.
在上面的代码中,我们使用 Proxy 来拦截 person
对象的 set
操作,并校验 age
属性的值是否为数字。如果不是数字,就抛出一个类型错误。
缓存代理
我们可以使用 Proxy 来实现一个简单的缓存机制,例如:
// javascriptcn.com 代码示例 const fibonacci = new Proxy( { 0: 0, 1: 1, }, { get(target, key, receiver) { if (!(key in target)) { target[key] = Reflect.get(target, key - 1) + Reflect.get(target, key - 2); } return Reflect.get(target, key, receiver); }, } ); console.log(fibonacci[10]); // 55 console.log(fibonacci[20]); // 6765
在上面的代码中,我们使用 Proxy 来拦截 fibonacci
对象的 get
操作,并实现了一个简单的斐波那契数列缓存机制。
隐藏属性
我们可以使用 Proxy 来隐藏对象的某些属性,例如:
// javascriptcn.com 代码示例 const hidden = new Proxy( { name: "John", age: 30, sex: "male", }, { get(target, key, receiver) { if (key.startsWith("_")) { throw new Error("Access denied."); } return Reflect.get(target, key, receiver); }, ownKeys(target) { return Reflect.ownKeys(target).filter((key) => !key.startsWith("_")); }, } ); console.log(hidden.name); // John console.log(hidden._age); // Error: Access denied. console.log(Object.keys(hidden)); // [ 'name', 'sex' ]
在上面的代码中,我们使用 Proxy 来拦截 hidden
对象的 get
和 ownKeys
操作,并隐藏了以 _
开头的属性。
总结
本文介绍了 ES6 中的 Proxy 和 Reflect,它们可以让开发者更加灵活地控制代码的行为。我们可以使用它们来实现数据校验、缓存代理、隐藏属性等功能。希望本文能对你理解 Proxy 和 Reflect 的用法及其应用有所帮助。
来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6558451dd2f5e1655d27987b