letprintUser = (property) => { let value = user[property]; if (!value) { thrownewError(`The property [${property}] does not exist`); } else { console.log(`The user ${property} is ${value}`); } }
printUser('name'); // 输出: 'The user name is John' printUser('email'); // 抛出错误: The property [email] does not exist
let proxy = newProxy(user, { get(target, property) { let value = target[property]; if (!value) { thrownewError(`The property [${property}] does not exist`); } return value; } });
letprintUser = (property) => { console.log(`The user ${property} is ${proxy[property]}`); };
printUser('name'); // 输出: 'The user name is John' printUser('email'); // 抛出错误: The property [email] does not exist
在上面的示例中,我们包装了 user 对象,并设置了一个 get 方法。 此方法充当拦截器,在返回值之前,会首先对属性值进行检查,如果不存在,则抛出异常。
输出与第一种情况相同,但此时 printUser 函数专注于逻辑,只处理消息。
set
代理可能有用的另一个例子是属性值验证。在这种情况下,我们需要使用 set 方法,并在其中进行验证。例如,当我们需要确保目标类型时,这是一个非常有用的钩子。我们来看一下实际使用:
1 2 3 4 5 6 7 8 9 10
let user = newProxy({}, { set(target, property, value) { if (property === 'name' && Object.prototype.toString.call(value) !== '[object String]') { // 确保是 string 类型 thrownewError(`The value for [${property}] must be a string`); }; target[property] = value; } });
user.name = 1; // 抛出错误: The value for [name] must be a string
这些是相当简单的用例,以下场景,proxy均可以派上用场:
格式化
价值和类型修正
数据绑定
调试
… 现在是时候创建一个更复杂的用例了。
具有代理的API - 更复杂的示例
通过使用简单用例中的知识,我们可以创建一个API包装器,以便在我们的应用程序中使用。 当前只支持 get 和 post 请求,但它可以很容易地扩展。代码如下所示。
get 在这里很有趣,它做了几件事。target 是一个空对象,get 方法将在第一次有人使用 api 时创建所有方法(如当前的 get 和 post请求),在 reduce 回调中,我们根据提供的配置执行API规范所需的验证和检查。在此示例中,我们不允许空URL和发布请求而不提供数据。这些检查可以扩展和修改,但重要的是我们只能在这一个地方集中处理。