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

相关推荐
风骏时光牛马4 分钟前
AI开源工具一站式体验:上手探索原生AI能力
前端
鬼手点金8 小时前
nanoGPT/nanochat 能做出 DeepSeek/Qwen 这样的大模型吗?
服务器·前端·javascript·bug·openclaw
软件技术NINI9 小时前
美妆商城html+Css+js 4页
javascript·css·html
蛋蛋的就会顺顺的9 小时前
hot100 p0——栈,贪心算法,动态规划
java·前端·javascript·算法·leetcode·力扣
程序员Sunday9 小时前
TypeScript 的 any、unknown、never 有什么区别?
前端·面试·typescript
朱涛的自习室9 小时前
70 美金的 Beyond Compare,我让 Gemini 4 和 DeepSeek 造个开源免费版(Day 2)
android·前端·人工智能
需要8269 小时前
Spring Bean 生命周期:从实例化到销毁的完整钩子
java·后端·spring
小 黄 鸡10 小时前
HashMap 面试必会知识点详解(JDK 8)
java·面试·职场和发展
码艺-Alimjan10 小时前
Tauri 源码备份 · 打包 & 解压 总结,源码收集之路
前端·javascript·vue.js
小马不起床10 小时前
零基础玩转 FastAPI_11:前端后台管理页面
前端·状态模式·fastapi