es6之Proxy,Reflect
Proxy 可以理解成,在目标对象之前架设一层“拦截”,外界对该对象的访问,都必须先通过这层拦截,因此提供了一种机制,可以对外界的访问进行过滤和改写。
var proxy = new Proxy(target, handler);
new Proxy()表示生成一个Proxy实例,target参数表示所要拦截的目标对象,handler参数也是一个对象,用来定制拦截行为。
如果handler没有设置任何拦截,那就等同于直接通向原对象。
var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.a = 'b';
target.a // "b"
上面代码中,handler是一个空对象,没有任何拦截效果,访问proxy就等同于访问target。
同一个拦截器函数,可以设置拦截多个操作。
//原始对象储存真实数据
let obj={
time:'2017-03-11',
name:'net',
_r:123
}; let monitor=new Proxy(obj,{
// 拦截对象属性的读取
get(target,key){
return target[key].replace('2017','2018')
},
// 拦截对象设置属性
set(target,key,value){
if(key==='name'){
return target[key]=value;
}else{
return target[key];
}
},
// 拦截key in object操作
has(target,key){
if(key==='name'){
return target[key]
}else{
return false;
}
},
// 拦截delete
deleteProperty(target,key){
if(key.indexOf('_')>-1){
delete target[key];
return true;
}else{
return target[key]
}
},
// 拦截Object.keys,Object.getOwnPropertySymbols,Object.getOwnPropertyNames
ownKeys(target){
return Object.keys(target).filter(item=>item!='time')
}
}); console.log(monitor.time);
//2018-03-11
monitor.time='2018';
monitor.name='mukewang';
console.log(monitor.time,monitor);
//2018-03-11 Proxy {time: "2017-03-11", name: "net", _r: 123}
console.log('name' in monitor,'time' in monitor);
//true false
console.log(Object.keys(monitor));
// ["name", "_r"]
Proxy 支持的拦截操作一览,一共 13 种。
- get(target, propKey, receiver):拦截对象属性的读取,比如
proxy.foo和proxy['foo']。 - set(target, propKey, value, receiver):拦截对象属性的设置,比如
proxy.foo = v或proxy['foo'] = v,返回一个布尔值。 - has(target, propKey):拦截
propKey in proxy的操作,返回一个布尔值。 - deleteProperty(target, propKey):拦截
delete proxy[propKey]的操作,返回一个布尔值。 - ownKeys(target):拦截
Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy)、for...in循环,返回一个数组。该方法返回目标对象所有自身的属性的属性名,而Object.keys()的返回结果仅包括目标对象自身的可遍历属性。 - getOwnPropertyDescriptor(target, propKey):拦截
Object.getOwnPropertyDescriptor(proxy, propKey),返回属性的描述对象。 - defineProperty(target, propKey, propDesc):拦截
Object.defineProperty(proxy, propKey, propDesc)、Object.defineProperties(proxy, propDescs),返回一个布尔值。 - preventExtensions(target):拦截
Object.preventExtensions(proxy),返回一个布尔值。 - getPrototypeOf(target):拦截
Object.getPrototypeOf(proxy),返回一个对象。 - isExtensible(target):拦截
Object.isExtensible(proxy),返回一个布尔值。 - setPrototypeOf(target, proto):拦截
Object.setPrototypeOf(proxy, proto),返回一个布尔值。如果目标对象是函数,那么还有两种额外操作可以拦截。 - apply(target, object, args):拦截 Proxy 实例作为函数调用的操作,比如
proxy(...args)、proxy.call(object, ...args)、proxy.apply(...)。 - construct(target, args):拦截 Proxy 实例作为构造函数调用的操作,比如
new proxy(...args)。
Proxy 实例的方法
下面是上面这些拦截方法的详细介绍。
get()
//原始对象储存真实数据
let obj={
time:'2017-03-11',
name:'net',
_r:123
}; let monitor=new Proxy(obj,{
// 拦截对象属性的读取
get(target,key){
return target[key].replace('2017','2018')
}
});
console.log(monitor.time,monitor);
//2018-03-11 Proxy {time: "2017-03-11", name: "net", _r: 123}
//只是读取显示的值变了,实际的值并没有改变
set()
//原始对象储存真实数据
let obj={
time:'2017-03-11',
name:'net',
_r:123
}; let monitor=new Proxy(obj,{
// 拦截对象属性的读取
get(target,key){
return target[key].replace('2017','2018')
},
// 拦截对象设置属性
set(target,key,value){
if(key==='name'){
return target[key]=value;
}else{
return target[key];
}
}
});
monitor.time='2018';
console.log(monitor.time);
//2017-03-11 set中设置不做改变
monitor.name='sun menghua';
console.log(monitor.time,monitor);
//2018-03-11 Proxy {time: "2017-03-11", name: "sun menghua", _r: 123}
//因为get monitor.time发生了改变
ownkeys()
for...in循环也受到ownKeys方法的拦截。
const obj = { hello: 'world' };
const proxy = new Proxy(obj, {
ownKeys: function () {
return ['a', 'b'];
}
});
for (let key in proxy) {
console.log(key); // 没有任何输出
}
上面代码中,ownkeys指定只返回a和b属性,由于obj没有这两个属性,因此for...in循环不会有任何输出。
Reflect
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API.
Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法。这就让Proxy对象可以方便地调用对应的Reflect方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy怎么修改默认行为,你总可以在Reflect上获取默认行为。
Reflect对象一共有 13 个静态方法。(似曾相识的13种)
- Reflect.apply(target, thisArg, args)
- Reflect.construct(target, args)
- Reflect.get(target, name, receiver)
- Reflect.set(target, name, value, receiver)
- Reflect.defineProperty(target, name, desc)
- Reflect.deleteProperty(target, name)
- Reflect.has(target, name)
- Reflect.ownKeys(target)
- Reflect.isExtensible(target)
- Reflect.preventExtensions(target)
- Reflect.getOwnPropertyDescriptor(target, name)
- Reflect.getPrototypeOf(target)
- Reflect.setPrototypeOf(target, prototype)
Reflect.get(target, name, receiver)
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
}
Reflect.get(myObject, 'foo') //
Reflect.get(myObject, 'bar') //
Reflect.get(myObject, 'baz') //
如果receiver存在,则函数的this绑定receiver。
var myObject = {
foo: 1,
bar: 2,
get baz() {
return this.foo + this.bar;
},
};
var myReceiverObject = {
foo: 4,
bar: 4,
};
Reflect.get(myObject, 'baz', myReceiverObject) //
{
let obj={
time:'2017-03-11',
name:'net',
_r:123
};
console.log(Reflect.get(obj,'time')); //2017-03-11
Reflect.set(obj,'name','sun menghua');
console.log(obj);
////{time: "2017-03-11", name: "sun menghua", _r: 123}
console.log(Reflect.has(obj,'name'));//true
}
es6之Proxy,Reflect的更多相关文章
- es6(11)--Proxy,Reflect
//Proxy,Reflect { let obj={ time:'2018-06-25', name:'net', _r:123 }; let monitor = new Proxy(obj,{ / ...
- [每日一题]面试官问:谈谈你对ES6的proxy的理解?
[每日一题]面试官问:谈谈你对ES6的proxy的理解? 关注「松宝写代码」,精选好文,每日一题 作者:saucxs | songEagle 一.前言 2020.12.23 日刚立的 flag,每日一 ...
- 详解es6中Proxy代理对象的作用
在es6中新添加了Proxy,那么它有什么作用啊?Proxy本意为代理,而es6中的Proxy也就是代理对象,那么代理对象感觉听起来很模糊,在这里就解释一下Proxy代理对象的作用. Proxy的主要 ...
- ES6的Proxy
最近在Javascript的设计编程中,用到的那个单例模式,感觉就类似一种代理的思想[其实就是缓存的一种机制],单例模式就是: function getSingle(fn){ var result; ...
- ES6中的元编程-Proxy & Reflect
前言 ES6已经出来好久了,但是工作中比较常用的只有let const声明,通过箭头函数改this指向,使用promise + async 解决异步编程,还有些数据类型方法...所以单独写一篇文章学习 ...
- ES6的Proxy和Reflect
Proxy 有一个原始的数据对象,通过代理出来一个新的对象,用户操作的是这个新的对象 { let obj ={ time:'2018-01-01', name:'lx' , _r:123 } let ...
- ES6走一波 Proxy/Reflect
Proxy:像拦截器,对目标对象修改等进行拦截,是一种元编程(meta programming),即修改JS语言本身. //生成proxy实例,两个参数都是对象,targetObj是要拦截的目标对象, ...
- es6之proxy和reflect
一.proxy //Proxy和Reflect //供应商 let obj={ time:"2017-11-21", name:"net", _r:123 } ...
- ES6初识-Proxy和Reflect
{ let obj={ time:'2017-03-11', name:'net', _r:123 }; let monitor=new Proxy(obj,{ // 拦截对象属性的读取 get( ...
随机推荐
- linux程序命令行选项的3种风格:unix、gnu、x toolkit
In Unix-like systems, the ASCII hyphen-minus is commonly used to specify options. The character is u ...
- PowerDesinger15设置字体大小
使用PowerDesigner时,它默认table的字体大小颜色等很难看: 假设通过 Symbol ---> Format进行设置.仅仅能对选中的最改动,新建的Table无效. 能够通过例如以下 ...
- mybatis中批量插入数据
<insert id="insertIntoDevAct" parameterType="java.util.List"><foreach c ...
- 使用 BenchmarkDotnet 测试代码性能 【Win10】单元测试中捕获异步方法的指定异常
先来点题外话,清明节前把工作辞了(去 tm 的垃圾团队,各种拉帮结派.勾心斗角).这次找工作就得慢慢找了,不能急了,希望能找到个好团队,好岗位吧.顺便这段时间也算是比较闲,也能学习一下和填掉手上的坑. ...
- BZOJ 1037: [ZJOI2008]生日聚会Party 四维DP
1037: [ZJOI2008]生日聚会Party Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1650 Solved: 971[Submit][ ...
- Python执行系统命令并获得输出的几种方法
[root@a upfc]# ./ffmpeg-linux64-v3.3.1 -i a.mp3 ffmpeg version N-86111-ga441aa90e8-static http://joh ...
- ios20--xib2
故事板控制器: // // ViewController.m // 03-通过xib自定义商品的View #import "ViewController.h" #import &q ...
- PSAM卡之常用APDU指令错误码【转】
本文转载自:http://blog.csdn.net/lvxiangan/article/details/53933714 PSAM卡的内容交互,是通过APDU指令完成的,常见的APDU报文格式如下: ...
- [疑问] C# 多线程程序,如果在并行程序块中开空间会远远慢于将空间开在并行块之外
// int[,] label = new int[m, n]; Parallel.For(, thread_num, (n) => { ]; i++) { int[] tmp = new in ...
- android 在代码中设置字体颜色 问题
项目中需要在代码中控制字体颜色 之前是直接引用资源文件 但是不行 tv.setTextColor(R.color.textColor_black); 无效果 后来在网上找了资料发现 要从reso ...