Reflect对象与Proxy对象一样,都是 ES6 为了操作对象而提供的新 API
1、Reflect
-
Reflect(反射)的设计目的:
-
将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
-
修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
-
让Object操作都变成函数行为。某些Object操作是命令式,比如name in obj和delete obj[name],而Reflect.has(obj, name)和Reflect.deleteProperty(obj, name)让它们变成了函数行为。
-
配合Proxy(代理)对象,完成代理对象修改源对象的默认行为。Reflect对象的方法与Proxy对象的方法一一对应,只要是Proxy对象的方法,就能在Reflect对象上找到对应的方法
-
-
Reflect 对象的静态方法
- Reflect.get(target, name, receiver)
Reflect.get方法查找并返回target对象的name属性,如果没有该属性,则返回undefined。 - Reflect.set(target, name, value, receiver)
Reflect.set方法设置target对象的name属性等于value - Reflect.has(target, name)
Reflect.has方法对应name in obj里面的in运算符。 - Reflect.deleteProperty(target, name)
Reflect.deleteProperty方法等同于delete obj[name],用于删除对象的属性。 - Reflect.construct(target, args)
Reflect.construct方法等同于new target(…args),这提供了一种不使用new,来调用构造函数的方法。 - Reflect.getPrototypeOf(target)
Reflect.getPrototypeOf方法用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj)。 - Reflect.setPrototypeOf(target, prototype)
Reflect.setPrototypeOf方法用于设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)方法。它返回一个布尔值,表示是否设置成功。 - Reflect.apply(target, thisArg, args)
Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数。 - Reflect.defineProperty(target, name, desc)
Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty代替它。 - Reflect.getOwnPropertyDescriptor(target, name)
Reflect.getOwnPropertyDescriptor基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象,将来会替代掉后者。 - Reflect.isExtensible(target)
Reflect.isExtensible方法对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。 - Reflect.preventExtensions(target)
Reflect.preventExtensions对应Object.preventExtensions方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。 - Reflect.ownKeys(target)
Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。
- Reflect.get(target, name, receiver)
2、Proxy
-
Proxy(代理)的设计目的:
- 用于修改某些操作的默认行为,等同于在语言层面做出修改,所以属于一种“元编程”(meta programming),即对编程语言进行编程。可以理解为,对目标对象(target)创建了一个代理对象(proxy),对该目标对象(target)的访问,都需要先通过代理对象(proxy)进行拦截,在代理对象中可以对外界的访问操作进行过滤和处理。
- ES6 原生提供 Proxy 构造函数,用来生成 Proxy 实例。
- 如果handler没有设置任何拦截,那就等同于直接通向原对象。
- 在拦截中可以通过Reflect(反射)将操作通向原对象
- 例如:Proxy 对象定义了一个目标(这里是一个空对象)和一个实现了 get 陷阱的 handler 对象。这里,代理的对象在获取未定义的属性时不会返回 undefined,而是返回 42。
let handler = { //Proxy 对象的get陷阱 get: function(target, name,receiver){ if(name in target){ //存在指定的属性,直接通过Reflect将操作通向目标对象的 return Reflect.get(target, name, receiver); } //没有指定的属性,总是返回42 return 42; } }; //为目标对象(这里是空对象),句柄handler对象用来定制拦截行为 let targetObj = {}; let p = new Proxy(targetObj, handler); //必须通过Proxy的实例对象进行操作才起作用(直接操作targetObj时Proxy是没有作用的) //访问p的a属性,是进入了Proxy定义的get陷阱 p.a = 1; console.log(p.a, p.b); // 1, 42
-
Proxy 对象可用的陷阱(拦截)
- 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)。
- get(target, propKey, receiver)