Proxy 与 Reflect:最硬核、最实用的解释

Proxy 与 Reflect:最硬核、最实用的解释

基本概念
Proxy

用来拦截对象的各种操作,包括读、写、删、函数调用等。类似于代理人,任何对对象的操作都要经过它。

js 复制代码
const proxy = new Proxy(target, handler)
  • target:要代理的目标对象
  • handler:一个对象,包含了拦截目标对象的函数。

常用的代理操作有读取属性(get)、属性设置(set)、存在属性(has)、属性删除(deleteProperty)、函数调用(apply)

js 复制代码
const handler = {
	get: function(target,property, receiver) {
		return target[property];
	},
	set:function(target,property,value,receiver) {
		target[property] = value;
		return true;
	},
	has: function(target,property) {
		return property === 'name' ? true : false
	},
	deleteProperty: function(target, property) {
		delete target[property]
		return true
	},
	apply:function(target, thisArg,argumentsList) {
		return target(argumentsList[0],argumentsList[1]) * 10
	}
}

const obj = {
	b: 10,
	get a() {
		return this.b;
	}
}

const proxy = new Proxy(obj, handler);
console.log(proxy.a)
Reflect

Reflect 是一个"工具类",是 ES6 新增的一个"内置操作 API 集 ",它把 JavaScript 引擎内部对对象执行的各种默认操作统一成了一套方法。提供与 Proxy 拦截方法 一一对应 的默认操作。

js 复制代码
Reflect.get(target, key)
Reflect.set(target, key, value) 
Reflect.deleteProperty(target, key) 

‍

为什么使用Proxy?

相比于Object.defineProperty(),Proxy 能够拦截对象的所有行为。

‍

为什么使用Reflect?

在 ES6 之前:

  • JS 引擎内部执行 getter、setter、delete、in 等操作都有 一套规范行为
  • 但 JS 开发者没有 API 可以直接调用这些规范操作

Proxy 出现后有个问题:

Proxy 的 get/set/delete 等拦截器,必须决定是:

  • 继续执行默认行为
  • 还是替换行为

但以前开发者无法"执行默认行为",只能写:

js 复制代码
target[key]
target[key] = value
delete target[key]

这些都不是 ECMA 规范层面的真正操作,会破坏:

  • 原型链查找规则
  • getter/setter 的 this 绑定
  • receiver 的传递
  • 返回值语义
  • 抛错语义

于是 Reflect 出现,用于:

提供所有内部操作的"规范等价方法"

‍

为什么Proxy和Reflect经常搭配使用?
  • 因为 Proxy 拦截后,需要用 Reflect 执行"默认行为"
  • 因为 Reflect 确保 this、原型链、返回值都符合语言规范
  • 因为 Reflect 参数与 Proxy handler 完全一致,天生配套
  • 因为直接操作 target 会导致 getter/setter/原型链错误
js 复制代码
const p = new Proxy(obj, {
  get(target, key, receiver) {
    return Reflect.get(target, key, receiver);
  },
  set(target, key, value, receiver) {
    console.log('setting', key);
    return Reflect.set(target, key, value, receiver);
  }
});

‍

相关推荐
子兮曰1 小时前
把 649 种文件格式塞进一个网页里:一个「文件不出浏览器」的预览器
前端·javascript·后端
paopaokaka_luck4 小时前
基于springboot+vue的智慧家政管理系统(AI问答、 WebSocket实时沟通、ECharts运营分析、订单规则与服务追踪)
java·javascript·spring boot·数据分析·echarts·mybatis
sm_926787054 小时前
RFID 标签打印的技术实现要点与二次开发实践
java·大数据·前端·c++·编辑器
IMPYLH5 小时前
HTML 的 <video> 元素
前端·html
溪语流沙5 小时前
【每天一个CSS | Day19】流光文字与一笔写成的手写签名
前端·javascript·css
逐光者9335 小时前
STM32——SPI 屏 · Flash · 高速
java·前端·stm32
To_OC6 小时前
同样是让 AI 写全栈,为什么别人一句话就够了
前端·前端框架·next.js
CDwenhuohuo6 小时前
electron pc项目打包成桌面端
前端·javascript·electron
前端大斗师6 小时前
「大于 1000」把 1000 元那单也算进去了:我在 Vue3 订单页对了 10 句话
前端·人工智能·typescript·大模型·原力计划
Jmyd01236 小时前
用 Web VR 引擎搭建 3D 虚拟展厅:从素材上云到多端实时渲染的完整数据链路
前端·3d·vr·三维数字化