静态方法
Reflect 对象一共有 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)
上面这些方法的作用,大部分与 Object 对象的同名方法的作用都是相同的,而且它与 Proxy 对象的方法是一一对应的。下面是对它们的解释。
Reflect.get(target, name, receiver)
Reflect.get
方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回 undefined。
如果 name 属性部署了读取函数(getter),则读取函数的 this 绑定 receiver。
如果第一个参数不是对象,Reflect.get
方法会报错。
Reflect.set(target, name, value, receiver)
Reflect.set
方法设置 target 对象的 name 属性等于 value。
如果 name 属性设置了赋值函数,则赋值函数的 this 绑定 receiver。
注意,如果 Proxy 对象和 Reflect 对象联合使用,前者拦截赋值操作,后者完成赋值的默认行为,而且传入了 receiver,那么 Reflect.set
会触发 Proxy.defineProperty
拦截。
上面代码中,Proxy.set
拦截里面使用了 Reflect.set
,而且传入了 receiver,导致触发 Proxy.defineProperty
拦截。这是因为 Proxy.set
的 receiver 参数总是指向当前的 Proxy 实例(即上例的obj),而 Reflect.set
一旦传入
receiver,就会将属性赋值到 receiver 上面(即obj),导致触发 defineProperty 拦截。如果 Reflect.set
没有传入 receiver,那么就不会触发 defineProperty 拦截。
如果第一个参数不是对象,Reflect.set
会报错。
Reflect.has(obj, name)
Reflect.has
方法对应 name in obj 里面的 in
运算符。
如果 Reflect.has
方法的第一个参数不是对象,会报错。
Reflect.deleteProperty(obj, name)
Reflect.deleteProperty
方法等同于 delete obj[name],用于删除对象的属性。
该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回 true;删除失败,被删除的属性依然存在,返回 false。
如果 Reflect.deleteProperty
方法的第一个参数不是对象,会报错。
Reflect.construct(target, args)
Reflect.construct
方法等同于 new target(...args),这提供了一种不使用 new,来调用构造函数的方法。
如果 Reflect.construct
方法的第一个参数不是函数,会报错。
Reflect.getPrototypeOf(obj)
Reflect.getPrototypeOf
方法用于读取对象的 __proto__
属性,对应 Object.getPrototypeOf(obj)
。
Reflect.getPrototypeOf
和 Object.getPrototypeOf
的一个区别是,如果参数不是对象,Object.getPrototypeOf
会将这个参数转为对象,然后再运行,而 Reflect.getPrototypeOf
会报错。
Reflect.setPrototypeOf(obj, newProto)
Reflect.setPrototypeOf
方法用于设置目标对象的原型(prototype),对应 Object.setPrototypeOf(obj, newProto)
方法。它返回一个布尔值,表示是否设置成功。
如果无法设置目标对象的原型(比如,目标对象禁止扩展),Reflect.setPrototypeOf
方法返回 false。
如果第一个参数不是对象,Object.setPrototypeOf
会返回第一个参数本身,而 Reflect.setPrototypeOf
会报错。
如果第一个参数是 undefined 或 null,Object.setPrototypeOf
和 Reflect.setPrototypeOf
都会报错。
Reflect.apply(func, thisArg, args)
Reflect.apply
方法等同于 Function.prototype.apply.call(func, thisArg, args)
,用于绑定 this 对象后执行给定函数。
一般来说,如果要绑定一个函数的 this 对象,可以这样写 fn.apply(obj, args)
,但是如果函数定义了自己的 apply 方法,就只能写成 Function.prototype.apply.call(fn, obj, args)
,采用 Reflect 对象可以简化这种操作。
Reflect.defineProperty(target, propertyKey, attributes)
Reflect.defineProperty
方法基本等同于 Object.defineProperty
,用来为对象定义属性。未来,后者会被逐渐废除,请从现在开始就使用 Reflect.defineProperty
代替它。
如果 Reflect.defineProperty
的第一个参数不是对象,就会抛出错误,比如 Reflect.defineProperty(1, 'foo')
。
这个方法可以与 Proxy.defineProperty
配合使用。
上面代码中,Proxy.defineProperty
对属性赋值设置了拦截,然后使用 Reflect.defineProperty
完成了赋值。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.getOwnPropertyDescriptor
基本等同于 Object.getOwnPropertyDescriptor
,用于得到指定属性的描述对象,将来会替代掉后者。
Reflect.getOwnPropertyDescriptor
和 Object.getOwnPropertyDescriptor
的一个区别是,如果第一个参数不是对象,Object.getOwnPropertyDescriptor(1, 'foo')
不报错,返回 undefined,而 Reflect.getOwnPropertyDescriptor(1, 'foo')
会抛出错误,表示参数非法。
Reflect.isExtensible (target)
Reflect.isExtensible
方法对应 Object.isExtensible
,返回一个布尔值,表示当前对象是否可扩展。
如果参数不是对象,Object.isExtensible
会返回 false,因为非对象本来就是不可扩展的,而 Reflect.isExtensible
会报错。
Reflect.preventExtensions(target)
Reflect.preventExtensions
对应 Object.preventExtensions
方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。
如果参数不是对象,Object.preventExtensions
在 ES5 环境报错,在 ES6 环境返回传入的参数,而 Reflect.preventExtensions
会报错。
Reflect.ownKeys (target)
Reflect.ownKeys
方法用于返回对象的所有属性,基本等同于 Object.getOwnPropertyNames
与 Object.getOwnPropertySymbols
之和。
如果 Reflect.ownKeys()
方法的第一个参数不是对象,会报错。