ES6 — Reflect 与 Proxy
1、Proxy(代理)
Proxy 可以对目标对象的读取、函数调用等操作进行拦截,然后进行操作处理。它不直接操作对象,而是像代理模式,通过对象的代理对象进行操作,在进行这些操作时,可以添加一些需要的额外操作。
一个 Proxy 对象由两个部分组成: target 、 handler 。在通过 Proxy 构造函数生成实例对象时,需要提供这两个参数。 target 即目标对象, handler 是一个对象,声明了代理 target 的指定行为。
Reflect 可以用于获取目标对象的行为,它与 Object 类似,但是更易读,为操作对象提供了一种更优雅的方式。它的方法与 Proxy 是对应的。
handler方法:
1、get()方法:获取target对象的属性时触发。get(target, propKey, receiver)
set()方法:设置target对象的属性时触发。set(target, propKey, value, receiver),注意,严格模式下,set代理如果没有返回true,就会报错。
参数 receiver 表示原始操作行为所在对象,一般是 Proxy 实例本身,recevier可以省略。
//目标对象 target
let target = {
name: 'Lamb',
age: '19'
}
//处理对象 handler
let handler = {
get : function(target, key){
console.log('要获取的元素的key是: '+key);
return target[key];
},
set : function(target, key, value){
console.log('要设置的元素的key: '+key);
target[key] = value;
}
}
let proxy = new Proxy(target, handler);
console.log('target的name是:'+proxy.name);
console.log('未更改之前target的age:'+proxy.age);
proxy.age = 20;//更改target对象的age属性,触发set函数
console.log('更改之后的age: '+proxy.age);
/*
要获取的元素的key是: name
target的name是:Lamb
要获取的元素的key是: age
未更改之前target的age:19
要设置的元素的key: age
要获取的元素的key是: age
更改之后的age: 20
*/
2、apply(target, ctx, args)函数
用于拦截函数的调用、call 和 reply 操作。target 表示目标对象(是一个函数),ctx 表示目标对象上下文,args 表示目标对象的参数数组。
function sub(a, b){
return a - b;
}
let handler = {
apply: function(target, ctx, args){
console.log('handle apply');
return Reflect.apply(...arguments);
}
}
let proxy = new Proxy(sub, handler)
console.log(proxy(2, 2));
// handle apply
// 0
3、has(target, propKey)
用于拦截 HasProperty 操作,即在判断 target 对象是否存在 propKey 属性时,会被这个方法拦截。此方法不判断一个属性是对象自身的属性,还是继承的属性。此方法不拦截 for ... in 循环。
let handler = {
has: function(target, propKey){
console.log("handle has");
return propKey in target;
}
}
let exam = {name: "Tom"}
let proxy = new Proxy(exam, handler)
console.log('name' in proxy)
// handle has
// true
4、construct(target, args),用于拦截 new 命令。返回值必须为对象。
5、deleteProperty(target, propKey),用于拦截 delete 操作,如果这个方法抛出错误或者返回 false ,propKey 属性就无法被 delete 命令删除。
6、defineProperty(target, propKey, propDesc),用于拦截 Object.definePro若目标对象不可扩展,增加目标对象上不存在的属性会报错;若属性不可写或不可配置,则不能改变这些属性。
7、getOwnPropertyDescriptor(target, propKey),用于拦截 Object.getOwnPropertyD() 返回值为属性描述对象或者 undefined 。
8、getPrototypeOf(target),主要用于拦截获取对象原型的操作。
9、isExtensible(target),用于拦截 Object.isExtensible 操作。该方法只能返回布尔值,否则返回值会被自动转为布尔值。
10、ownKeys(target),用于拦截对象自身属性的读取操作。
11、preventExtensions(target),拦截 Object.preventExtensions 操作。该方法必须返回一个布尔值,否则会自动转为布尔值。
12、setPrototypeOf,主要用来拦截 Object.setPrototypeOf 方法。返回值必须为布尔值,否则会被自动转为布尔值。若目标对象不可扩展,setPrototypeOf 方法不得改变目标对象的原型。
13、Proxy.revocable(),用于返回一个可取消的 Proxy 实例。
……太多了!记不住,需要的时候查文档了……
2、Reflect
ES6 中将 Object 的一些明显属于语言内部的方法移植到了 Reflect 对象上(当前某些方法会同时存在于 Object 和 Reflect 对象上),未来的新方法会只部署在 Reflect 对象上。
Reflect 对象对某些方法的返回结果进行了修改,使其更合理。
Reflect 对象使用函数的方式实现了 Object 的命令式操作。
1、Reflect.get(target, name, receiver),查找并返回 target 对象的 name 属性。
2、Reflect.set(target, name, value, receiver),将 target 的 name 属性设置为 value。返回值为 boolean ,true 表示修改成功,false 表示失败。当 target 为不存在的对象时,会报错。
3、Reflect.has(obj, name),是 name in obj 指令的函数化,用于查找 name 属性在 obj 对象中是否存在。返回值为 boolean。如果 obj 不是对象则会报错 TypeError。
……

浙公网安备 33010602011771号