小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。
Proxy 和 Relection 让 JavaScript 这门语言也可以支持元编程(Meta programming),让程序去实现程序。同时 vue3 对于响应式数据实现也从 getter 和 setter 方式转移为 Proxy 和 Relection 方式,所以有必要把这部分内容好好了解一下,自己也抽出时间整理一下希望有助于大家更了解 JavaScript 的新特性。
对于对象上的大多数操作,在 JavaScript 规范中都有一个所谓的 "内部方法",描述了在最低层的工作方式。例如[[Get]],读取一个属性的内部方法,[[Set]],写入一个属性的内部方法。这些方法只在规范中使用,无法我们直接调用这些方法的名字。
let proxy = new Proxy(target, handler)
| 内部方法 | 拦截器方法 | 触发场景 |
|---|---|---|
[[Get]] | get | 读取属性 |
[[Set]] | set | 写入属性 |
[[HasProperty]] | has | in 操作 |
通过对 get 方法设置拦截器实现默认值
最常见的拦截器是为读/写属性设置的拦截器。为了拦截读取,处理程序应该有一个 get(target, property, receiver)方法。
当一个属性被读取时,就会触发这个拦截器,参数如下。
let target = {};
let proxy = new Proxy(target, {}); // 空 handler
proxy.test = 5; // writing to proxy (1)
alert(target.test); // 5,
alert(proxy.test); // 5,
for(let key in proxy) alert(key);
- target - 是目标对象,作为第一个参数传递给 new Proxy 的对象
- property - 属性名称
- receiver - 如果目标属性是一个 getter,receiver 参数是指定调用这个函数的对象,也就是
this指向的对象。通常是 Proxy 对象自己(可以是继承 Proxy 的对象)。暂时我们忽略这个参数,以后会有更详细的解释。
设定 get 返回的默认值
通常当试图从数组获取一个不存在的数组项时,例如该索引已经越界,默认情况下会得到未定义的结果,但我们将把一个普通的数组包裹在代理中,它可以捕获读取,如果没有这样的属性则返回 0。
let numbers = [0, 1, 2];
numbers = new Proxy(numbers, {
get(target, prop) {
if (prop in target) {
return target[prop];
} else {
return 0; // default value
}
}
});
alert( numbers[1] ); // 1
alert( numbers[123] ); // 0
更多例子随后带给大家,希望大家多多支持。