Vue面试必须会的Proxy
什么是Proxy
Proxy是ECMAScript新增的api。可以为开发者提供拦截并向基本操作嵌入额外的行为的能力。
Proxy可以给目标定义一个相关联的代理对象,而这个代理对象可以作为抽象的目标对象来使用。在对目标对象的各种操作影响目标对象之前,可以在代理对象中对这些操作加以控制。
大部分现代浏览器均已支持,支持用户的比例已经非常接近Object: defineProperty
96.31% Proxy 97.33% Object: defineProperty
定义捕获器
我认为Proxy的精髓就是捕获器。
使用代理的主要目的是可以定义捕获器(trap)
。捕获器
就是在处理程序对象中定义的“基本操作的拦截器”。每个处理程程序对象可以包含零个或多个捕获器,每个捕获器都对应一种基本操作,可以直接或间接在代理对象上调用。每次在代理对象上调用这些基本操作时,代理可以在这些操作传播到目标对象之前先调用捕获器函数,从而拦截并修改相应的行为。
捕获器(trap)
是从操作系统中借用的概念。在操作系统中,捕获器是程序流中的一个同步中断,可以暂停程序流,转而执行一段子例程,之后再返回原始程序流。
以最常用的set为例:
捕获set()基本操作
set()捕获器会在设置属性值的操作中被调用。对应的反射API方法为Reflect.set()。
const myTarget ={}
const proxy = new Proxy (myTarget,{
set(target,property,value,receiver){
console.log ('set ()')
return Reflect.set (..arguments)
}
});
proxy.foo ='bar';
1.返回值
返回true表示成功;返回false表示失败,严格模式下会抛出TypeError。
2.拦截的操作
- proxy.property = value
- Object.create(proxy)[property] = value
- proxy [property]=value
- Reflect.set(proxy,property,value,receiver)
3.捕获器处理程序参数
- property:引用的目标对象上的字符串键属性。
- target:目标对象。
- value:要赋给属性的值。
- receiver:接收最初赋值的对象。
如果target.property不可写且不可配置,则不能修改目标属性的值。
4.捕获器不变式
如果target.property不可写且不可配置,则不可修改目标属性的值。
如果target.property不可配置且[[set]]特性为undefined,则不能修改目标属性的值。
在严格模式下,处理程序中返回false会抛出TypeError。
捕获其他基本操作
代理的捕获器
可以捕获13种不同的基本操作。这些操作有各自不同的反射API方法、参数、关联ECMAScript操作和不变式。
下面列出几个可捕获的,常用的基本操作。
捕获get()基本操作
get()捕获器会在获取属性值的操作中被调用。对应的反射AP方法为Ref1ect.get()。
const myTarget ={}
const proxy = new Proxy (myTarget,{
get(target,property,receiver){
console.log ('get ()')
return Reflect.get(..arguments)
}
});
proxy.foo;
1.返回值
返回值无限制。
2.拦截的操作
- proxy.property
- Object.create(proxy)[property]
- proxy [property]
- Reflect.get(proxy,property,,receiver)
3.捕获器处理程序参数
- property:引用的目标对象上的字符串键属性。
- target:目标对象。
- receiver:代理对象或继承代理对象的对象。
如果target.property不可写且不可配置,则不能修改目标属性的值。
4.捕获器不变式
如果target.property不可写且不可配置,则处理程序返回的值必须与target.property匹配。
如果target.property不可配置且[[Get]]特性为undefined,处理程序的返回值也必须是undefined。
捕获has()基本操作
const myTarget ={}
const proxy = new Proxy (myTarget,{
has(target,property){
console.log ('has ()')
return Reflect.has(..arguments)
}
});
'foo'in proxy;
1.返回值
has()必须返回布尔值,表示属性是否存在。返回非布尔值会被转型为布尔值。
2.拦截的操作
- property in proxy
- property in Object.create(proxy)
- with(proxy){(property);}
- Reflect.has(proxy,property)
3.捕获器处理程序参数
- target:目标对象。
- property:引用的目标对象上的字符串键属性。
4.捕获器不变式
如果target.property存在且不可配置,则处理程序必须返回true。
如果target.property存在且目标对象不可扩展,则处理程序必须返回true。
捕获apply()基本操作
apply()捕获器会在调用函数时中被调用。对应的反射AP方法为Retlect,apply()。
const myTarget =() => {}
const proxy = new Proxy (myTarget,{
apply(target,thisArg,...argumentsList){
console.log ('apply()')
return Reflect.apply(...arguments)
}
});
proxy();
捕获construct()基本操作
construct()捕获器会在new操作符中被调用。对应的反射API方法为Reflect.construct()。
const myTarget =() => {}
const proxy = new Proxy (myTarget,{
apply(target,argumentsList,newTarget){
console.log ('construct()')
return Reflect.construct(...arguments)
}
});
new proxy();
1.返回值
construct()必须返回一个对象。
2.拦截的操作
- new proxy(...argumentsList)
- Reflect.construct(target,argumentsList,newTarget)
3.捕获器处理程序参数
- target:目标构造函数。
- argumentsList:传给目标构造函数的参数列表。
- newTarget:最初被调用的构造函数。
4.捕获器不变式
target必须可以用作构造函数。
参考: 《JavaScript高级程序设计》 https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
相关文章
- [KDD 2022 | 论文简读] 面向Top-K推荐的多方面量化强化二值化图表示学习
- [ICML 2022 | 论文简读] 面向图表示学习的结构感知的Transformer
- [Nat. Commun. | 论文简读] 将生物医学数据集成和格式化为 Bioteque 中预先计算的知识图谱嵌入
- [Nature Communication | 论文简读] 将生物医学数据集成和格式化为Bioteque中预先计算的知识图谱嵌入
- [arxiv | 论文简读] CLASSIC: 方面级情感分类任务的持续和对比学习
- 欢常见的Web安全方面问题
- 面试系列-kafka exactly once语义
- 面试系列-kafka消息相关机制
- 面试系列-kafka内部通信协议
- 面试系列-kafka高可用机制
- 面试系列-kafka偏移量提交
- 面试系列-kafka事务控制
- 面试系列-kafka基础组件及其关系
- 面试系列之-rocketmq重试队列和死信队列
- 面试系列之-rocketmq文件数据存储
- 面试系列之-rocketmq长轮询模式
- 面试系列之-rocketmq零拷贝原理
- 面试系列之-rocketmq组件及关系
- 面试系列之-rocketmq消息机制
- 面试系列之-rocketmq高可用