Proxy详解

Proxy 在ES6 中引入,用于创建一个对象的代理。本文介绍了JavaScript中的Proxy对象,如何通过handler函数实现对象属性的拦截和自定义操作,以及get,set,delete Property等方法的用法和注意事项。还探讨了Proxy在拦截外部访问、数据类型验证、私有属性保护和观察者模式中的应用。

var proxy = new Proxy(target, handler)

关于handler 可拦截属性共有14种(方法13个),如下:

handler.getPrototypeOf() : Object.getPrototypeOf 方法的捕捉器。

handler.setPrototypeOf() : Object.setPrototypeOf 方法的捕捉器。

handler.isExtensible() : Object.isExtensible 方法的捕捉器。

handler.preventExtensions():Object.preventExtensions 方法的捕捉器。

handler.getOwnPropertyDescriptor():Object.getOwnPropertyDescriptor 方法的捕捉器。

handler.defineProperty() :Object.defineProperty 方法的捕捉器。

handler.has() :in 操作符的捕捉器。

handler.get() :属性读取操作的捕捉器。

handler.set() :属性设置操作的捕捉器。

handler.deleteProperty() :delete 操作符的捕捉器。

handler.ownKeys() :Object.getOwnPropertyNames 方法和 Object.getOwnPropertySymbols 方法的捕捉器。

handler.apply() :函数调用操作的捕捉器。

handler.construct() :new 操作符的捕捉器。

getPrototypeOf(target): 拦截Object.getPrototypeOf(proxy),返回一个对象

setPrototypeOf(target, proto):拦截Object.setPrototypeOf(proxy, proto),返回一个布尔值

isExtensible(target): 拦截Object.isExtensible(proxy),返回一个布尔值

get(target,propKey,receiver):拦截对象属性的读取

set(target,propKey,value,receiver):拦截对象属性的设置

has(target,propKey):拦截propKey in proxy的操作,返回一个布尔值

deleteProperty(target,propKey):拦截delete proxy[propKey]的操作,返回一个布尔值

ownKeys(target):拦截Object.keys(proxy)、for...in等循环,返回一个数组

getOwnPropertyDescriptor(target, propKey):拦截Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象

defineProperty(target, propKey, propDesc):拦截Object.defineProperty(proxy, propKey, propDesc),返回一个布尔值

preventExtensions(target):拦截Object.preventExtensions(proxy),返回一个布尔值

apply(target, object, args):拦截 Proxy 实例作为函数调用的操作

construct(target, args):拦截 Proxy 实例作为构造函数调用的操作

【Reflect】

若需要在Proxy内部调用对象的默认行为,建议使用Reflect,其是ES6中操作对象而提供的新 API

基本特点:

只要Proxy对象具有的代理方法,Reflect对象全部具有,以静态方法的形式存在

修改某些Object方法的返回结果,让其变得更合理(定义不存在属性行为的时候不报错而是返回false)

让Object操作都变成函数行为

=== 可撤销的代理对象 ===

Proxy.revocable() 方法可以用来创建一个可撤销的代理对象。

// revocable 其结构为: {"proxy": proxy, "revoke": revoke},其中:

var revocable = Proxy.revocable(

{},

{

get(target, name) {

return "[[" + name + "]]";

},

},

);

var proxy = revocable.proxy;

proxy.foo; // "[[foo]]"

revocable.revoke();

console.log(proxy.foo); // 抛出 TypeError

proxy.foo = 1; // 还是 TypeError

delete proxy.foo; // 又是 TypeError

typeof proxy; // "object",因为 typeof 不属于可代理操作

=== 延伸阅读 14种可代理对象具体含义 ===

1、Object.getPrototypeOf(obj) : 指定对象的原型。

静态方法返回指定对象的原型(即内部 [[Prototype]] 属性的值)。

参数:obj 要返回其原型的对象。

2、Object.setPrototypeOf(obj, prototype) : 无返回值。

参数:obj 要设置其原型的对象; prototype 该对象的新原型(一个对象或 null)。

静态方法可以将一个指定对象的原型(即内部的 [[Prototype]] 属性)设置为另一个对象或者 null。

注意:应该避免设置对象的 [[Prototype]] 属性。而是使用 Object.create() 创建一个具有所需 [[Prototype]] 属性的新对象。

3、Object.isExtensible(obj) : 布尔值

Object.isExtensible() 静态方法判断一个对象是否是可扩展的(是否可以在它上面添加新的属性)。

参数:obj 要设置其原型的对象;

默认情况下,对象是可扩展的:可以向它们添加新属性,并且它们的 [[Prototype]] 可以被重新赋值。

如果传入的参数不是一个对象,那么它将返回 false 而不会报错,因为按照定义,原始类型是不可变的。

相关推荐
a1117762 小时前
PreTeXt 开源推荐(应用demo)
前端·开源·html
鬼先生_sir2 小时前
SpringBoot-源码剖析
java·spring boot·springboot源码解析
追光的蜗牛丿2 小时前
C++传递参数时什么情况下传递引用
开发语言·javascript·c++
ch.ju2 小时前
Java程序设计(第3版)第二章——Java中的数据类型
java
MwEUwQ3Gx2 小时前
深入理解 Java Deque 的设计哲学
java·开发语言·python
麦芽糖02192 小时前
若依整合AI一 基础应用篇
java
进朱者赤2 小时前
从 Java / Go 后端视角系统理解 TypeScript 与 Node.js:从看不懂到能参与 openclaw 这类项目开发
java·golang·typescript
摸鱼仙人~2 小时前
前端开发中“共享预览链接”场景-企业级最简方案:Vue + 极简后端(2 接口 1 张表)
前端·javascript·vue.js
MX_93592 小时前
SpringMVC静态资源访问、annotation-driven的使用原理及数据响应模式
java·后端·spring