ES6之Proxy 的巧用
摘要: proxy的骚操作。
- 作者:前端小智
- 原文:proxy 的巧用
fundebug经授权转载,版权归原作者所有。
proxy 介绍
使用proxy
,你可以将一只猫伪装成一只老虎。下面大约有6个例子,我希望它们能让你相信,proxy 提供了强大的 javascript 元编程。
尽管它不像其他es6功能用的普遍,但proxy
有许多用途,包括,对象模拟,简洁而灵活的api创建,,甚至vue 3背后的内部响应系统提供动力。
proxy
用于修改某些操作的默认行为,也可以理解为在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。这个词的原理为代理,在这里可以表示由它来“代理”某些操作,译为“代理器”。
es6原生提供了proxy
构造函数,用来生成proxy
实例。
var proxy = new proxy(target, handler);
proxy
对象的所有用法,都是上面的这种形式。不同的只是handle
参数的写法。其中new proxy
用来生成proxy
实例,target
是表示所要拦截的对象,handle
是用来定制拦截行为的对象。
下面是 proxy 最简单的例子是,这是一个有陷阱的代理,一个get
陷阱,总是返回42
。
let target = { x: 10, y: 20 }; let hanler = { get: (obj, prop) => 42 }; target = new proxy(target, hanler); target.x; //42 target.y; //42 target.x; // 42
结果是一个对象将为任何属性访问操作都返回“42”。 这包括target.x
,target['x']
,reflect.get(target, 'x')
等。
但是,proxy 陷阱当然不限于属性的读取。 它只是十几个不同陷阱中的一个:
- handler.get
- handler.set
- handler.has
- handler.apply
- handler.construct
- handler.ownkeys
- handler.deleteproperty
- handler.defineproperty
- handler.isextensible
- handler.preventextensions
- handler.getprototypeof
- handler.setprototypeof
- handler.getownpropertydescriptor
proxy 用例
默认值/“零值”
在 go 语言中,有的概念,零值是特定于类型的隐式默认结构值。其思想是提供类型安全的默认基元值,或者用gopher的话说,给结构一个有用的零值。
虽然不同的创建模式支持类似的功能,但javascript无法用隐式初始值包装对象。javascript中未设置属性的默认值是undefined
。但 proxy 可以改变这种情况。
const withzerovalue = (target, zerovalue) => new proxy(target, { get: (obj, prop) => (prop in obj ? obj[prop] : zerovalue) });
函数withzerovalue
用来包装目标对象。 如果设置了属性,则返回属性值。 否则,它返回一个默认的“零值”。
从技术上讲,这种方法也不是隐含的,但如果我们扩展withzerovalue
,以boolean (false
), number (0
), string (""
), object ({}
),array ([]
)等对应的零值,则可能是隐含的。
let pos = { x: 4, y: 19 }; console.log(pos.x, pos.y, pos.z); // 4, 19, undefined pos = withzerovalue(pos, 0); console.log(pos.z, pos.y, pos.z); // 4, 19, 0
此功能可能有用的一个地方是坐标系。 绘图库可以基于数据的形状自动支持2d和3d渲染。 不是创建两个单独的模型,而是始终将z
默认为 0
而不是undefined
,这可能是有意义的。
负索引数组
在js中获取数组中的最后一个元素方式通过写的很冗长且重复,也容易出错。 这就是为什么有一个tc39提案定义了一个便利属性array.lastitem
来获取和设置最后一个元素。
其他语言,如python和ruby,使用负组索引更容易访问最后面的元素。例如,可以简单地使用arr[-1]
替代arr[arr.length-1]
访问最后一个元素。
使用 proxy 也可以在 javascript 中使用负索引。
const negativearray = els => new proxy(els, { get: (target, propkey, receiver) => reflect.get( target, +propkey < 0 ? string(target.length + +propkey) : propkey, receiver ) });
一个重要的注意事项是包含handler.get的陷阱字符串化所有属性。 对于数组访问,我们需要将属性名称强制转换为numbers
,这样就可以使用一元加运算符简洁地完成。
现在[-1]
访问最后一个元素,[-2]
访问倒数第二个元素,以此类推。
const unicorn = negativearray(["