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(["
ES6之Proxy 的巧用的更多相关文章
- ES6的Proxy
最近在Javascript的设计编程中,用到的那个单例模式,感觉就类似一种代理的思想[其实就是缓存的一种机制],单例模式就是: function getSingle(fn){ var result; ...
- 详解es6中Proxy代理对象的作用
在es6中新添加了Proxy,那么它有什么作用啊?Proxy本意为代理,而es6中的Proxy也就是代理对象,那么代理对象感觉听起来很模糊,在这里就解释一下Proxy代理对象的作用. Proxy的主要 ...
- [每日一题]面试官问:谈谈你对ES6的proxy的理解?
[每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- 深度揭秘ES6代理Proxy
最近在博客上看到关于ES6代理的文章都是一些关于如何使用Proxy的例子,很少有说明Proxy原理的文章,要知道只有真正掌握了一项技术的原理,才能够写出精妙绝伦的代码,所以我觉得有必要写一篇关于深刻揭 ...
- ES6之Proxy及Proxy内置方法
Proxy是ES6提供的代理器可以起到拦截作用,写法形式如 var proxy = new Proxy(target,handler);参数target表示要拦截的目标对象,handler是用来定制拦 ...
- es6之Proxy,Reflect
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写. var proxy = new Proxy(ta ...
- ES6 之 Proxy
概述 Proxy 用于修改某些操作的默认行为,等同于在语言层面做出修改. Proxy 可以理解在目标对象架设一个“拦截”层外界对该对象的访问都必须先通过这层拦截,因此提供了一种机制可以对外界的访问进行 ...
- ES6的Proxy和Reflect
Proxy 有一个原始的数据对象,通过代理出来一个新的对象,用户操作的是这个新的对象 { let obj ={ time:'2018-01-01', name:'lx' , _r:123 } let ...
- es6(11)--Proxy,Reflect
//Proxy,Reflect { let obj={ time:'2018-06-25', name:'net', _r:123 }; let monitor = new Proxy(obj,{ / ...
随机推荐
- JDK、JVM、JRE关系
开始第一个Java程序 *保证计算机当中已经安装了文本编辑器EditPlus *安装JDK[JDK一般需要从oracle的官网下载],我们这里先用的JDK7 *在安装JDK的时候有jre JDK开发需 ...
- python session保持登录,新增地址,并删除,由观察可知,address_id决定删除的内容;
import requests,reheaders={"User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64) Ap ...
- POJ3662Telephone Lines(最短路+二分)
传送门 题目大意:n个点p条边,每条边有权值,让1和n点联通,可以将联通1--n的边选k条免费, 求剩下边权的最大值. 题解:二分一个答案x,大于x的边权设为1,小于等于x的边权设为0,跑最短路. 若 ...
- Python保存json文件并格式化
使用json.dump()的时候设置一下indent参数的值就好了.比如json.dump(json_dict, f, indent=4), ensure_ascii=False,写入中文
- C#,WPF,DataGrid,Excel,导出
private void btnExport_Click(object sender, RoutedEventArgs e) { System.Diagnostics.Stopwatch sw = n ...
- 练手WPF(四)——贪吃蛇小游戏的简易实现(上)
一. 游戏界面首先,按照惯例,编辑MainWindow.xaml,先将游戏界面制作好.非常简单:(1)主游戏区依然使用我们熟悉的Canvas控件,大小为640X480像素,设定每小格子为20px,所以 ...
- Winforn中设置ZedGraoh的GraphPane恢复到初始比例大小
场景 Winform中实现ZedGraph中曲线右键显示为中文: https://blog.csdn.net/BADAO_LIUMANG_QIZHI/article/details/100115292 ...
- C++调用linux命令并获取返回值
qt中封装了相关的方法, 但是因为我的命令中用到了管道命令, 出现了非预期结果, 所有改用了linux系统原生的方法. 下边是一个判断某进程是否存在的例子. 当前存在一个问题,当linux返回多行时, ...
- C#下的时间测试(用于计算方法执行时间)
public class Timing { private TimeSpan m_StartTime; private TimeSpan duringTime; public Timing() //构 ...
- Python - 常规操作Excel - 第二十六天
前言 作为一名资深程序员,通过代码熟练操作Excel是必不可少的技能,本章主要讲解Python通过openpyxl第三方库(官方文件说明)对Excel进行操作,使Excel程序化操作更为简单快捷. o ...