概述
Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect 对象的设计目的有这样几个。
1, 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上。现阶段,某些方法同时在 Object 和Reflect对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。
2,修改某些 Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc) 则会返回 false。
3, 让 Object 操作都变成函数行为。某些 Object 操作是命令式,比如name in obj和delete obj[name],而 Reflect.has(obj, name) 和 Reflect.deleteProperty(obj, name) 让它们变成了函数行为。
ps: in 运算符 如果指定的属性在指定的对象或其原型链中,则in 运算符 返回 true ,否者返回false。
4, Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。
Reflect 对象上的方法
Reflect 对象上的方法详细解释
Reflect.get(target, name, receiver)
Reflect.get 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回undefined。
eg:
另外,关于Reflect.get方法的第三个参数是可选的,当你没有传这个参数时,如果 target 对象的 name 属性部署了读取函数(getter),则读取函数的 this 绑定的还是 target。
如果你传入了第三个参数,且 target 对象的 name 属性部署了读取函数(getter),则读取函数的 this 绑定的是你传入的那个参数。
eg:
Reflect.set(target, name, value, receiver)
Reflect.set 方法设置 target 对象的 name属性等于 value (即将 value 赋值给 target 对象的name)。
从图中可以看出,两个属性都赋值给了空对象 obj,这种操作是没有毛病滴。
关于Reflect.get方法的第四个参数(receiver)是可选的,同get方法一样,当你没有传这个参数时,如果 target 对象的 name 属性部署了赋值函数(setter),则读取函数的 this 绑定的还是 target。
如果你传入了第三个参数,且 target 对象的 name 属性部署了赋值函数(setter),则读取函数的 this 绑定的是你传入的那个参数。
Reflect.has(obj, name)
Reflect.has 方法对应 name in obj 里面的 in 运算符。
如果第一个参数不是对象,Reflect.has 和 in 运算符都会报错。
Reflect.deleteProperty(obj, name)
Reflect.deleteProperty 方法等同于delete obj[name],用于删除对象的属性。
该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回 true;删除失败,被删除的属性依然存在,返回 false。
Reflect.construct(target, args)
Reflect.construct 方法等同于 new target(...args),这提供了一种不使用 new,来调用构造函数的方法。
第一个参数是一个构造函数,第二个参数是一个数组。
Reflect.getPrototypeOf(obj)
Reflect.getPrototypeOf 方法用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj)。
Reflect.defineProperty(target, propertyKey, attributes)
Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。唯一不同是返回 Boolean 值。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty代替它。
ps(Object.defineProperty() ):
Object.defineProperty() 方法会直接在一个对象上定义一个新属性,或者修改一个对象的现有属性, 并返回这个对象。
语法:
Object.defineProperty(obj, prop, descriptor)
obj
要在其上定义属性的对象。
prop
要定义或修改的属性的名称。
descriptor(对象形式)
将被定义或修改的属性描述符。
什么是属性描述符:
对象里目前存在的属性描述符有两种主要形式:数据描述符和存取描述符。数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由getter-setter函数对描述的属性。描述符必须是这两种形式之一;不能同时是两者。
数据描述符和存取描述符均具有以下可选键值:
configurable
当且仅当该属性的 configurable 为 true 时,该属性描述符才能够被改变,同时该属性也能从对应的对象上被删除。默认为 false。
enumerable
当且仅当该属性的enumerable为true时,该属性才能够出现在对象的枚举属性中。默认为 false。
数据描述符同时具有以下可选键值:
value
该属性对应的值。可以是任何有效的 JavaScript 值(数值,对象,函数等)。默认为 undefined。
writable
当且仅当该属性的writable为true时,value才能被赋值运算符改变。默认为 false。
存取描述符同时具有以下可选键值:
get
一个给属性提供 getter 的方法,如果没有 getter 则为 undefined。当访问该属性时,该方法会被执行,方法执行时没有参数传入,但是会传入this对象(由于继承关系,这里的this并不一定是定义该属性的对象)。默认为 undefined。
set
一个给属性提供 setter 的方法,如果没有 setter 则为 undefined。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。
描述符可同时具有的键值:
如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。
ps: 这个知识点蛮大的,举两个例子:
1,属性描述符中的 writable 属性(Object.defineProperty(obj, prop, descriptor)中的descriptor是一个对象形式):
当writable属性设置为false时,该属性被称为“不可写”。它不能被重新分配(控制对象是否可以被修改,默认为 false。但是我们的对象都是继承自原型的,原型上它为true,所以可以被修改)。
2,enumerable定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。
从图中可以看出,in 运算符是可以的,但是使用for..in循环遍历的时候是找不到它的~
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.preventExtensions(obj) 阻止对象扩展!
Reflect.preventExtensions(target)
Reflect.preventExtensions 对应 Object.preventExtensions 方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。
Reflect.ownKeys (target)
Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。