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

相关推荐
GIS阵地几秒前
QgsSingleBandPseudoColorRenderer 完整详解(QGIS 3.40.13 C++)
开发语言·前端·c++·qt·qgis
刘较瘦_20 分钟前
AI 开发中的 Git Submodule 父子仓库模式:前后端分仓管理与协作实践
前端·github
yaoxin52112328 分钟前
470. Java 反射 - Member 接口与 AccessFlag
java·开发语言·python
牧艺33 分钟前
cos-design WeatherBackground:用 Canvas 做一个「会变天」的背景引擎
前端·canvas·视觉设计
OpenTiny社区37 分钟前
深度解析 LSP 如何为 AI 装上“眼睛”
前端·ai编程
做个文艺程序员44 分钟前
Linux第24篇:Java应用监控体系搭建:Prometheus+Grafana可视化运维
java·grafana·prometheus
布列瑟农的星空1 小时前
流程类SVG画布的通用开发范式
前端
fsssb1 小时前
Chromium 源码学习笔记(七):那些跨进程的调用,底下都是同一个东西——Mojo
前端
gis开发之家1 小时前
《Vue3 从入门到大神35篇》Vue3 源码详解(五):effect 依赖收集原理——track 与 trigger 是如何工作的?
javascript·typescript·前端框架·vue3·vue3源码
MichaelJohn1 小时前
从零星白屏到“启发式缓存”,记录一次刚接手屎山的惊险排查
前端