Proxy 与 Reflect
学习 es6 的新语法糖既能学习到新东西,又能使得自己的代码更加优雅,逼格更高,爽 proxy 与 Reflect 之间的运用就是 Reflect 对对象的操作触发 Proxy 的拦截
Proxy 是对对象进行代理,通过 proxy 生成的对象间接操作原本对象,最常见的就是 get 与 set;语法形式 var proxy = new Proxy(target, handler); target 是需要操作的对象,而 handler 是包含操作 target 对象的一些方法的对象
Reflect 是能够更加优雅的使用 Object 的相关方法
学习 API
get
proxy: get(target, propKey, receiver)=> 依次为目标对象、属性名和 proxy 实例本身(严格地说,是操作行为所针对的对象),其中最后一个参数可选。
let obj = {
a: ‘foo’,
b: ‘Proxy’,
foo: ”
}
let proxy = new Proxy(obj, {
get (target, proKey, receive) {
console.log(target === obj) //true
return ‘ 当对 proxy 进行取值操作时会触发这个 get 函数 ’
}
})
ps:proxy 对 target 进行了代理,target 就是 obj 对象,receive 用于规定 this 到底指向哪个对象,
proxy.foo // 当对 proxy 进行取值操作时会触发这个 get 函数
上面这种情况并没有改变 this 的,所以 console.log(receive === proxy) //trueReflect 也有 get 方法:Reflect.get(target, prokey, receive)
Reflect.get(proxy, ‘foo’) // 同上没有 this 的指向
let newobj = {
foo: ‘this 指向将改变 ’
}
Reflect.get(proxy, ‘foo’, newobj) //foo = console.log(receive === proxy) //true
所以对 Reflect.get 的第三个参数进行赋值将带入带 proxy 的 get 的第三个参数中
set
与 get 类似,这个是赋值时会触发 set 方法 proxy: set(target, propKey, value, receiver)
let obj = {}
let newobj = {
a: ‘123’
}
let proxy = new Proxy(obj, {
set (target, proKey, value, receive) {
return target[proKey] = ` 当对 proxy 进行赋值操作时会触发这个 set 函数 ${value}`
}
})
proxy.a = 666 //receive === proxy true
Reflect.set(proxy, ‘a’, 888) //receive === proxy true
Reflect.set(proxy, ‘a’, 888, newobj) //receive === newobj true
apply
proxy 的 apply:apply(target, object, args)
let twice = {
apply (target, ctx, args) {
console.log(ctx) //undefined
return Reflect.apply(…arguments);
}
}
function sum (left, right) {
this.num = 888 / 如果 ctx 没有传入或者传入 null,则会进行 window.num = 888 的赋值
return left + right + this.nm
}
let obj = {
nm: 666
}
var proxy = new Proxy(sum, twice);
console.log(proxy(1, 2)) // 6
console.log(proxy.apply(obj, [7, 8])) //ctx 则为 obj, 并改变 return
执行流程:proxy 触发函数调用,执行 apply 的方法,将参数自动带入,target 就是 sum 函数,ctx 没有传入为 undefined,args 为 1, 2, 接下来将全部参数带入执行 Reflect.apply
has
has 比较简单,是对对象进行 in 运算,判断该属性是否存在对象中,可以是自身也可以是原型链上,不管是否可遍历
construct
在构造函数 new 时触发,
var p = new Proxy(function () {}, {
construct: function(target, args, newTarget) {
console.log(‘called: ‘ + args.join(‘, ‘));
console.log(newTarget === p)
return {value: args[0] * 10 };
}
});
console.log((new p(1)).value)
// 等价于下面,Reflect.construct(target, args),args 必须是数组
console.log(Reflect.construct(p, [1]))
ownKeys
返回对象中自身的所有属性,当然具体还是取决于 return 什么内容;
触发条件:
Object.getOwnPropertyNames()
Object.getOwnPropertySymbols()
Object.keys()
for…in 循环
let target = {
a: 1,
b: 2,
c: 3,
[Symbol.for(‘secret’)]: ‘4’,
};
Object.defineProperty(target, ‘key’, {
enumerable: false,
configurable: true,
writable: true,
value: ‘static’
});
let handler = {
ownKeys(target) {
return [‘a’, ‘d’, Symbol.for(‘secret’), ‘key’];
}
};
let proxy = new Proxy(target, handler);
console.log(Object.keys(proxy)) // 自动过滤 symbol,不存在的属性,不可遍历的属性
console.log(Reflect.ownKeys(proxy)) // 返回 handler 中 return 的值