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 proxypropKey的操作,返回一个布尔值

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 而不会报错,因为按照定义,原始类型是不可变的。

相关推荐
文丑颜不良啊35 分钟前
LeetCode2481~2500题目解析
java·leetcode
程序员大阳1 小时前
HTML+CSS+JS对话式实战(5)-活动管理页之查看报名名单的实现
javascript·css·html·查看报名名单
Flynn Liang2 小时前
同一需求三套写法:用 Spring AI、LangChain4j、AgentScope Java 各实现一个带工具调用的 RAG 助手(实战对比)
java·人工智能·大模型·架构设计·spring ai·langchain4j·agentscope
曦樂~2 小时前
【Web Development】02 CSS
前端·css
风骏时光牛马2 小时前
后端服务接口开发与数据逻辑处理
前端
东鹏特饮2 小时前
经典打砖块(Breakout)游戏
前端·css·css3
聪明的笨猪猪2 小时前
实际工程问题:AI 生成 Spring Cache(@Cacheable / @CachePut / @CacheEvict)缓存注解踩坑
java·经验分享·面试·ai编程
IT_陈寒2 小时前
Vite的HMR把我整不会了:一个生产环境的热更新坑
前端·人工智能·后端
Mh2 小时前
如何使用双缓冲优化视频切换
前端
愿有所息2 小时前
记一次 ARM64 + JDK8 上 fastjson2 的诡异数据错乱
java