什么是 Proxy?
Proxy 是 ES6 引入的新特性之一,可以说 Proxy 是 ES6 对面向对象编程的一次全新尝试,它能够拦截并改变底层操作的默认行为,这里的底层操作包括了对象的访问、属性的读取、赋值和删除等。
Proxy 的基本使用
-- -------------------- ---- ------- --- --- - --- --------- - ----------- ---- --------- - -------------------- ---------- ------ ------------------- ---- ---------- -- ----------- ---- ------ --------- - -------------------- ---------- ------ ------------------- ---- ------ ---------- - --- --------- - -- -- ------- ------ ------------ -- ------- ------ -- ------- ------
上面的代码中,我们定义了一个空对象 obj
,并将其转化成一个 Proxy 对象,使用 Proxy 的第一个参数为代理对象,第二个参数为一个 Handler 对象,它定义了与代理对象相关的一些操作,比如 get 和 set。当我们在代理对象 obj
上进行操作时,get 和 set 会被自动捕获并执行。
在上面的例子中,当我们给 obj
设置新属性或更新属性时,会先执行 set 方法,并打印出 setting count!
的日志;当我们获取属性时,则会先执行一次 get 方法,并打印出 getting count!
的日志。
Proxy 的高级使用
属性拦截之 defineProperty
我们知道,在 ES5 中,我们可以使用 Object.defineProperty()
方法来定义一个对象的属性,并且可以为属性赋予 getter 和 setter。Proxy 提供了与 Object.defineProperty()
相关的拦截方法,让我们能够为拦截对象的属性赋予更多的附加行为。
-- -------------------- ---- ------- ----- ------- - - ---------------------- ---- ----------- - ---------------- -------- ------ ------------------------------ ---- ------------ - -- ----- --- - --- --------- --------- --------- - -- -- ----- ----
在上面的代码中,我们设置了一个 handler
对象,使用 defineProperty
方法拦截了对 obj
对象的属性定义操作。当我们定义属性时,会先执行 handler 中的 defineProperty 方法,并打印出 count 被定义了
的日志。
方法拦截之 apply
当我们使用某个对象的方法时,不一定是这个对象本身调用方法,这个方法可能是继承、混合等方式实现的。Proxy 提供了方法拦截器来控制方法的执行。
-- -------------------- ---- ------- ----- ------- - - ------ ---------------- -------- ----- - ------------------ ----------------- ------ --------------------- -------- ------ - -- -------- ---- - --------------- ----- - ----- ----- - --- --------- --------- -------- -- ----- -- -- -- --
在上面的代码中,我们定义了一个普通的函数 fn
,使用 Proxy 将其转换成了代理函数 proxy
,使用 apply
方法拦截了对 proxy
函数的调用。当我们调用代理函数时,会先执行 apply
方法,并打印出 函数调用: ${target.name}
的日志,然后再执行函数本身并打印出 执行 fn
的日志。
Reflect 的使用
Reflect 是 ES6 新增的一个全局对象,它提供了大量的操作方法,这些方法的作用与 Proxy 的 handler 方法相同,但是它们不是拦截器,而是可以直接调用的工具方法,更加方便高效。
我们可以使用 Reflect 的方法来操作对象,而不必使用 Proxy 的 handler 方法。比如,我们可以使用 Reflect 的 set
方法来替代 Proxy 的 set
方法。
-- -------------------- ---- ------- ----- ------ - - -- -- -- -- -- - -- ----- ----- - --- ------------- - ----------- ---- ------ --------- - ---------------- ------ - ----------- ------ ------------------- ---- ------ ---------- - --- ------- - --- -- --- - - --
在上面的代码中,我们使用 Proxy 的 set
方法拦截了对 Proxy 对象的属性赋值操作。当我们设置 proxy.a
时,会打印出 set a = 10
的日志。
我们可以使用 Reflect 的 set
方法来替代 Proxy 的 set
方法,在使用 Reflect.set
方法时,如果被设置的属性存在于对象上,则直接设置;如果不存在,则返回 false。下面是使用 Reflect.set 的例子:
-- -------------------- ---- ------- ----- ------ - - -- -- -- -- -- - -- ----- ----- - --- ------------- - ----------- ---- ------ --------- - ---------------- ------ - ----------- ------ ------------------- ---- ------ ---------- - --- ------------------ ---- --- -- --- - - -
总结
Proxy 和 Reflect 是 ES6 新增的两个对象,它们提供了强大的拦截器和更加方便的操作方法,使得我们在使用 JavaScript 进行编程时,更加灵活高效。
Proxy 可以拦截对象的各种操作,包括读取和赋值对象属性,定义和删除对象属性等等,而 Reflect 则提供了一组操作对象的工具方法,让我们能够更加自如地操作对象。
在平时的开发中,我们可以根据实际需要选择使用 Proxy 和 Reflect,来使我们的代码更加简洁、清晰和易于维护。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64659840968c7c53b0645d16