概述


Reflect 对象与 Proxy 对象一样,也是 ES6 为了操作对象而提供的新 APIReflect 对象的设计目的有这样几个。

1, 将 Object 对象的一些明显属于语言内部的方法(比如 Object.defineProperty ),放到 Reflect 对象上。现阶段,某些方法同时在 Object Reflect对象上部署,未来的新方法将只部署在 Reflect 对象上。也就是说,从 Reflect 对象上可以拿到语言内部的方法。

2,修改某些 Object 方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc) 在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc) 则会返回 false。




es6判断包含对象的数组是否有undefined_运算符


3, 让 Object 操作都变成函数行为。某些 Object 操作是命令式,比如name in objdelete obj[name],而 Reflect.has(obj, name) Reflect.deleteProperty(obj, name) 让它们变成了函数行为。


es6判断包含对象的数组是否有undefined_es6 对象中是否有键值_02


ps: in 运算符 如果指定的属性在指定的对象或其原型链中,则in 运算符 返回 true ,否者返回false。

4, Reflect 对象的方法与 Proxy 对象的方法一一对应,只要是 Proxy 对象的方法,就能在Reflect 对象上找到对应的方法。这就让 Proxy 对象可以方便地调用对应的 Reflect 方法,完成默认行为,作为修改行为的基础。也就是说,不管 Proxy 怎么修改默认行为,你总可以在 Reflect 上获取默认行为。


es6判断包含对象的数组是否有undefined_描述符_03


Reflect 对象上的方法


es6判断包含对象的数组是否有undefined_数据_04


Reflect 对象上的方法详细解释

Reflect.get(target, name, receiver)

Reflect.get 方法查找并返回 target 对象的 name 属性,如果没有该属性,则返回undefined

eg:


es6判断包含对象的数组是否有undefined_数据_05


另外,关于Reflect.get方法的第三个参数是可选的,当你没有传这个参数时,如果 target 对象的 name 属性部署了读取函数(getter),则读取函数的 this 绑定的还是 target。


es6判断包含对象的数组是否有undefined_描述符_06


如果你传入了第三个参数,且 target 对象的 name 属性部署了读取函数(getter),则读取函数的 this 绑定的是你传入的那个参数

eg:


es6判断包含对象的数组是否有undefined_es6 对象中是否有键值_07


Reflect.set(target, name, value, receiver)

Reflect.set 方法设置 target 对象的 name属性等于 value (即将 value 赋值给 target 对象的name)。


es6判断包含对象的数组是否有undefined_描述符_08


从图中可以看出,两个属性都赋值给了空对象 obj,这种操作是没有毛病滴。

关于Reflect.get方法的第四个参数(receiver)是可选的,同get方法一样,当你没有传这个参数时,如果 target 对象的 name 属性部署了赋值函数(setter),则读取函数的 this 绑定的还是 target。


es6判断包含对象的数组是否有undefined_es6 对象中是否有键值_09


如果你传入了第三个参数,且 target 对象的 name 属性部署了赋值函数(setter),则读取函数的 this 绑定的是你传入的那个参数

Reflect.has(obj, name)

Reflect.has 方法对应 name in obj 里面的 in 运算符。


es6判断包含对象的数组是否有undefined_数据_10


如果第一个参数不是对象,Reflect.has in 运算符都会报错。

Reflect.deleteProperty(obj, name)

Reflect.deleteProperty 方法等同于delete obj[name],用于删除对象的属性。


es6判断包含对象的数组是否有undefined_数据_11


该方法返回一个布尔值。如果删除成功,或者被删除的属性不存在,返回 true;删除失败,被删除的属性依然存在,返回 false


es6判断包含对象的数组是否有undefined_数据_12


Reflect.construct(target, args)

Reflect.construct 方法等同于 new target(...args),这提供了一种不使用 new,来调用构造函数的方法。


es6判断包含对象的数组是否有undefined_数据_13


第一个参数是一个构造函数,第二个参数是一个数组。


es6判断包含对象的数组是否有undefined_描述符_14


Reflect.getPrototypeOf(obj)

Reflect.getPrototypeOf 方法用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj)


es6判断包含对象的数组是否有undefined_数据_15


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(对象形式)

将被定义或修改的属性描述符。


es6判断包含对象的数组是否有undefined_es6 对象中是否有键值_16


什么是属性描述符:

对象里目前存在的属性描述符有两种主要形式:数据描述符存取描述符数据描述符是一个具有值的属性,该值可能是可写的,也可能不是可写的。存取描述符是由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。当属性值修改时,触发执行该方法。该方法将接受唯一参数,即该属性新的参数值。

描述符可同时具有的键值:


es6判断包含对象的数组是否有undefined_数据_17


如果一个描述符不具有value,writable,get 和 set 任意一个关键字,那么它将被认为是一个数据描述符。如果一个描述符同时有(value或writable)和(get或set)关键字,将会产生一个异常。

ps: 这个知识点蛮大的,举两个例子:

1,属性描述符中的 writable 属性(Object.defineProperty(obj, prop, descriptor)中的descriptor是一个对象形式):

当writable属性设置为false时,该属性被称为“不可写”。它不能被重新分配(控制对象是否可以被修改,默认为 false。但是我们的对象都是继承自原型的,原型上它为true,所以可以被修改)。


es6判断包含对象的数组是否有undefined_数据_18


2,enumerable定义了对象的属性是否可以在 for...in 循环和 Object.keys() 中被枚举。


es6判断包含对象的数组是否有undefined_数据_19


从图中可以看出,in 运算符是可以的,但是使用for..in循环遍历的时候是找不到它的~

Reflect.getOwnPropertyDescriptor(target, propertyKey)

Reflect.getOwnPropertyDescriptor 基本等同于 Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象,将来会替代掉后者。


es6判断包含对象的数组是否有undefined_运算符_20


Reflect.getOwnPropertyDescriptorObject.getOwnPropertyDescriptor的一个区别是,如果第一个参数不是对象,Object.getOwnPropertyDescriptor(1, 'foo')不报错,返回undefined,而Reflect.getOwnPropertyDescriptor(1, 'foo')会抛出错误,表示参数非法。

Reflect.isExtensible (target)

Reflect.isExtensible 方法对应 Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展。


es6判断包含对象的数组是否有undefined_数据_21


使用 Object.preventExtensions(obj) 阻止对象扩展!


es6判断包含对象的数组是否有undefined_es6 对象中是否有键值_22


Reflect.preventExtensions(target)

Reflect.preventExtensions 对应 Object.preventExtensions 方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功。


es6判断包含对象的数组是否有undefined_运算符_23


Reflect.ownKeys (target)

Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和。


es6判断包含对象的数组是否有undefined_数据_24