Reflect 反射是 ES6 新增的一个内置对象,提供了很多方法用来操作 JS 对象。也就是说,可以用 Reflect 来代替 Object 统一操作 JS 对象。
Reflect 与 Math 对象类似,所有的属性和方法都是静态的,不是一个构造函数,不能对其进行调用。
Reflect 出现的原因:
Reflect 对象的设计目的有这样几个:
- 将 Object 上只针对对象本身的方法,放到 Reflect 对象上。比如
Reflect.defineProperty()
。 - 修改某些 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)
让它们变成了函数行为。 - Reflect 对象的方法与 Proxy 对象的方法一一对应,只要 Proxy 能够定义的方法 Reflect 也能找到。
Reflect 的常见方法:
Reflect.get(target, key, receiver)
:相当于target[key]
。用来获取对象的属性值。第三个参数 receiver 的作用是,如果遇到对象的 getter,receiver 就是 getter 调用时的 this。const person = { name: 'Lee' } // Object 的写法: console.log(person.name) // Lee // Reflect 的写法: console.log(Reflect.get(person, 'name')) // Lee
Reflect.set(target, key, value, receiver)
:相当于targer[key] = value
。用来设置对象的属性值。第三个参数 receiver 的作用是,如果遇到对象的 setter,receiver 就是 setter 调用时的 this。返回值是一个布尔值,表示是否设置成功。let person = { _name: 'Lee', // 2. 通过这种方式设置 name,其实是设置了两次 person 的属性,一次是 name,一次是 _name。但是因为 this 指向 person,而不是代理对象,因此设置 _name 不会被 Proxy 捕获 set name(value) { this._name = value}, get name() { return this._name } } const proxy = new Proxy(person, { set: function(target, key, value, receiver) { // 1. 设置 person.name target[key] = value console.log('Proxy 的 set 方法被调用了') // 只会打印一次 } }) proxy.name = 'Mary' console.log(person.name)
let person = { _name: 'Lee', // 2. 通过这种方式设置 name,其实是设置了两次 person 的属性,一次是 name,一次是 _name。通过 Reflect 传入的第四个参数改变了 this 的指向,因此设置 _name 也会被 Proxy 捕获 set name(value) { this._name = value }, get name() { return this._name} } const proxy = new Proxy(person, { set: function(target, key, value, receiver) { // 1. 通过 Reflect 设置 person.name // 使用 Reflect 的好处:1. 不再直接操作原对象;2. Reflect 的方法有返回值,可以方便地判断操作是否成功;3. 通过给 Reflect 的 set 方法传递第四个参数,可以修改对象的 setter 方法调用时的 this Reflect.set(target, key, value, receiver) console.log('Proxy 的 set 方法被调用了') // 会打印两次 } }) proxy.name = 'Mary' console.log(person.name)
Reflect.has(target, key)
:相当于 in 运算符。用来判断对象的属性是否存在。返回值是一个布尔值。Reflect.deleteProperty(target, key)
:相当于 delete 操作符。用来删除对象的属性。返回值是一个布尔值。Reflect.apply(func, thisArg, arg)
:相当于Function.prototype.apply.call(func, thisArg, argsList)
。用来绑定 this 对象后调用给定的函数。Reflect.construct(target, argsList, newTarget)
:相当于 new 操作符。用来对构造函数进行 new 操作。第一个参数是要执行的构造函数,第二个参数是参数列表,第三个参数是最终创建出来的对象的类型。也就是说,new target()
执行第一个参数中的代码,并传入第二个参数中的元素作为其参数,但是创建出来的对象的隐式原型指向的是第三个参数的显示原型。function Person(name, age) { this.name = name this.age = age } function Student(name, age) { } const stu1 = new Student('Lee', 18) console.log(stu1) // stu1 中是没有任何属性 // 相当于 new Person() 执行 Person 构造函数中的代码,并传入 Lee 和 18 作为其参数,但是让 stu2.__prpto__ 指向 Student.prototype const stu2 = Reflect.construct(Person, ['Lee', 18], Student) console.log(stu2) // stu2 中有 name 属性和 age 属性
Reflect.ownKeys(target)
:相当于Object.getOwnPropertyNames()
与Object.getOwnPropertySymbols()
之和。用来获取对象的所有属性。返回值是一个布尔值。Reflect.defineProperty(target, key)
:对应Object.defineProperty()
。用来为对象定义属性。Reflect.getOwnPropertyDescriptor(target, key)
:对应Object.getOwnPropertyDescriptor()
。用于获取对象属性的描述对象。Reflect.getPrototypeOf(target)
:对应Object.getPrototypeOf()
。用来获取对象的隐式原型。Reflect.setPrototypeOf(target, prototype)
:对应Object.setPrototypeOf()
。用来设置对象的隐式原型。返回值是一个布尔值。Reflect.isExtensible (target)
:对应Object.isExtensible()
。表示当前对象是否可扩展。返回值是一个布尔值。Reflect.preventExtensions(target)
:对应Object.preventExtensions()
。用来设置使一个对象变为不可扩展。返回值是一个布尔值。