JavaScript 路线图—Proxy 和 Relection(1)

385 阅读2分钟

小知识,大挑战!本文正在参与“程序员必备小知识”创作活动。

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]]hasin 操作

通过对 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 

更多例子随后带给大家,希望大家多多支持。