随着ECMAScript 2015的出现,大量的功能出现了。 其中一些使您生气,而另一些则带来令人惊喜的惊喜,例如长时间相识之后遇到老朋友。
一些功能与元编程有关。 那是什么 我说的不是很好,所以让我们谈谈我们的朋友Wikipedia。
元编程是一种编程技术,其中计算机程序具有将其他程序视为其数据的能力。 这意味着可以将程序设计为读取,生成,分析或转换其他程序,甚至在运行时对其进行修改。 在某些情况下,这使程序员可以最大程度地减少表达解决方案的代码行数,从而减少开发时间。 它还使程序具有更大的灵活性,可以有效地处理新情况而无需重新编译。
简而言之,元编程允许程序在编译和执行时操纵其他人或他们自己。 JavaScript中的元编程基于两个功能:Proxy和Reflect API。 在这篇文章中,我们将考虑第一个。
代理人
代理是一种新的API,允许在运行时拦截,修改和扩展对象。 使用此API,您可以:
- 分析和调试日志,
- 拦截对属性的调用,
- 验证“即时”,
- 等
代理是一个接受两个参数的构造函数:源对象和充当源对象处理程序的对象。 后者包含称为陷阱的方法。
陷阱是一种修改对象某些部分行为的方法。 例如,陷阱获取和设置拦截分别调用属性以获取和建立值,从而能够在此过程之前和之中放置逻辑。
为了更好地了解代理的有用性,让我们做一些小练习。
示例:记录/分析
想象一下,您已经17岁了,即将满18岁。 并且您希望您的程序在打开时自动向您祝贺。 为此,您可以使用代理。
et person = { name: "John Doe", age: 17 }; person = new Proxy(person, { set(target, property, value) { if (value === 18) { console.log("Congratulations! You are of legal age"); Reflect.set(target, property, value); return true; } } }); person.age = 18; Not only can we do logs, as I said at the beginning, we can do as far as the language limits us. Here we could make validations for the age, for example, if it exceeds 100 that throw us an error: if (value < 13 && value > 99) { throw new Error('The age should be between 13 and 99') } else { Reflect.set(target, property, value) } Example: secure access to properties let person = { name: "John Doe" }; const Undefined = new Proxy( {}, { get(target, name, receiver) { return Undefined; } } ); const Safeish = obj => { return new Proxy(obj, { get(target, property, receiver) { if (target.hasOwnProperty(property)) { const isObject = target[property] instanceof Object; return isObject ? Safeish(target[property]) : Reflect.get(target, property, receiver); } return Undefined; } }); }; person = Safeish(person); console.log(person.name); console.log(person.sister.name === Undefined);
示例:查询数组
我们已经看到了一个使用最常用的get和set陷阱的示例。 为了加强功能,让我们进一步介绍并使用嵌套代理。 本练习将尝试将常规数组转换为可查询数组,以使用像经典SQL groupBy这样的运算符。
为此,我们将需要两个输入参数:
- 集合:我们将扩展的对象数组。
- groupKeys:字符串数组,表示要分组的属性(名称,类别,价格等)
const data = [ { id: 1, category: 2, name: "Intel NUC Hades Canyon" }, { id: 2, category: 1, name: "Logitech K380" }, { id: 3, category: 1, name: "Genius ECO-8100" } ]; const groupable = (collection, groupKeys) => {
return new Proxy(clone, { get(target, property, receiver) { if (property === "groupBy") { return new Proxy(target[property], { get(target, property, receiver) {
结论
代理可能不是最常用的ES6功能,但与Reflect API一起,它是最重要和有趣的功能之一。 它的灵活性允许在多种情况下采用它,最重要的是,它易于实现。
参考文献
https://es.wikipedia.org/wiki/Metaprogramaci%C3%B3n