Javascript Proxy对象 简介
本文转载自:众成翻译
译者:eJayYoung
链接:http://www.zcfy.cc/article/4755
原文:https://blog.campvanilla.com/advanced-guide-javascript-proxy-objects-introduction-301c0fce9432
Javascript Proxy对象
改变你操作对象的方式
Proxies 是Javasript对象的中间件
…或者说至少是那种很早的版本。
ES6 中引入Proxies,让你可以自定义Object
的基本操作。例如,get
就是Object
的基础操作方法。
const obj = {val: 10
};
console.log(obj.val);
这里,console.log()
表达式在对象obj
上执行get
方法来获取val
的值。
另一个对象的基本操作方法是 set
。
const obj = {val: 10
};
obj.val2 = 20;
这里,set
方法用来给对象obj
设置一个新的值。
如何创建Proxy?
const proxiedObject = new Proxy(initialObj, handler);
调用Proxy构造函数,new Proxy()
将返回一个对象,不仅包含了initialObj
里的值,而且其基本操作(如get
和 set
)现在可以通过handler
对象来指定一些自定义逻辑。
我们写个例子来理解这个概念,
const handler = {get: function() {console.log('A value has been accessed');}
}const initialObj = {id: 1,name: 'Foo Bar'
}const proxiedObj = new Proxy(initialObj, handler);console.log(proxiedObj.name);
现在,如果我们没有构造一个Proxy对象,执行第14行的console.log(proxiedObj.name)
会在控制台输出 “Foo Bar”。
不过现在我们定义了一个Proxy,并在第三行get
方法中定义了一些自定义逻辑。
现在执行console.log(proxiedObj.name)
会在控制台输出 “A value has been accessed”。
仔细看,你会发现控制台中实际上有两条记录。 “A value has been accessed” 和 undefined
。 为什么?��
get
运算符的默认实现是返回Object中存储的值。由于我们将它重写为只记录一条语句,该值永远不会返回,因此第14行的console.log()
输出undefined
。
让我们来解决这个问题!
get
运算符有两个参数 - 对象本身和被访问的属性。
const handler = {get: function(obj, prop) {console.log('A value has been accessed');return obj[prop]; // 返回访问的key在obj的值}
}const initialObj = {id: 1,name: 'Foo Bar'
}const proxiedObj = new Proxy(initialObj, handler);console.log(proxiedObj.name);
返回属性值 好多了吧! ��
我们为get
提供的自定义覆盖被称为“拦截器”(大概基于操作系统拦截的概念)。 handler
对象基本上是一个包含一组“拦截”的对象,每当访问对象属性时都会被触发。
我们给set
也添加一个“拦截器”。 我们将做同样的事情 - 任何时候设置一个值,我们将记录被修改的属性,以及为该键设置的值。
set
操作符有三个参数 - 对象本身,被访问的属性和为该属性设置的值。
const handler = {get: function(obj, prop) {console.log('A value has been accessed');return obj[prop];},set: function(obj, prop, value) {console.log(`${prop} is being set to ${value}`);}
}const initialObj = {id: 1,name: 'Foo Bar'
}const proxiedObj = new Proxy(initialObj, handler);proxiedObj.age = 24
添加set
“拦截器” 这里,在第18行进行的访问将触发第6行定义的功能,该功能将记录正在访问的属性和正在设置的值。
Set
“拦截器” —— 控制台的输出 一个真实的例子
假设我们有一个定义叫person的对象
const person = {id: 1,name: 'Foo Bar'
};
如果我们想让这个对象的id属性是一个私有属性呢? 没人能够通过person.id访问这个属性,如果有人这样做,我们需要抛出一个错误。 我们将如何做到这一点?
让Proxies来拯救吧!������
我们所需要做的就是给这个对象创建一个Proxy,并覆盖get
运算符来阻止我们访问id
属性!
const handler = {get: function(obj, prop) {if (prop === 'id') { // Check if the id is being accessedthrow new Error('Cannot access private properties!'); // Throw an error} else {return obj[prop]; // If it's not the id property, return it as usual}}
}const person = {id: 1,name: 'Foo Bar'
}const proxiedPerson = new Proxy(person, handler);console.log(proxiedPerson.id);
阻止访问私有属性 这里,在我们给get
创建的“拦截器”,我们检查被访问的属性是否是id
属性,如果是的话,我们会抛出一个错误。 否则,我们照常返回值。
另一个极好的用例是校验。 通过设置set
“拦截器”,我们可以在设置值之前添加自定义验证。 如果该值不符合验证,我们可以抛出一个错误!
const handler = {set: function(obj, prop, value) {if (typeof value !== 'string') {throw new Error('Only string values can be stored in this object!');} else {obj[prop] = value;}}
}const obj = {};const proxiedObj = new Proxy(obj, handler);console.log(proxiedObj); // This will log an empty object
proxiedObj.name = 'Foo Bar'; // This should be allowed
console.log(proxiedObj); // This will log an object with the name property setproxiedObj.age = 24; // This will throw an error.
自定义对象的属性校验 自定义校验 - 控制台输出 在上面的例子中,我们已经看到了get
和set
“陷阱”。 实际上可以设置更多的“陷阱”。 你可以在这里找到整个列表。
Proxy对象只是在阅读关于它们的这篇文章之后才进入我的视野,我已经可以在我每天写的代码中看到它们的用处了!
如果你之前在项目或工作中使用过Proxies,我很乐意听到!��
~最后~
如果您觉得这篇文章对您有用,请点个赞��!
在什么地方卡住了,需要更多的帮助,还是只想打个招呼? 在Hashnode 给我直接发问题,或者在Twitter上Call我。 你也可以在Github上找到我。��