Reflect
设计目的
- 将Object对象上一些明显属于语言内部的方法,放在Reflect对象中,未来新的方法只部署在Reflect对象上。即从Reflect内部可以获取语言内部的方法,比如Object.defineProperty
- 修改Object对象中某些方法的返回结果,让其变得更加合理。比如Object.defineProperty在无法定义属性时抛出错误,而Reflect.defineProperty则会返回false
- 让Object的命令式操作变成函数行为。比如name in obj变为Reflect.has(obj, name);delete obj[name]变为Reflect.delete(obj, name)
- 只要是Proxy对象的方法,就能在Reflect找到对应的方法。确保在Proxy修改了原有的默认行为后,仍然能够在Reflect获取对应的默认行为
静态方法
- Reflect.get(target, name, receiver)
- 查找并返回target对象的name属性,未找到返回undefined
- 若name属性部署了读取函数getter,且具有receiver(没有传入receiver,默认target为receiver),则读取函数getter中的this指向receiver
- 若target不是一个对象,该方法会报错
- Reflect.set(target, name, receiver)
- 设置target对象的name属性为value
- 若name属性设置了存值函数setter,则存值函数setter的this指向receiver
- 若在Proxy.set中(拦截赋值操作)使用Reflect.set(完成赋值操作的默认行为),且将receiver传入了Reflect.set,则Reflect.set会触发Proxy.defineProperty拦截。因为Proxy.set的receiver参数指向Proxy实例本身,而一旦将receiver传入Reflect.set(未传入则不会触发),就会将属性赋值到receiver对象上面,导致触发Proxy.defineProperty
- 若target不是一个对象,该方法会报错
- Reflect.has(obj, name)
- 该方法对应于name in obj的in运算符
- 第一个参数不是对象,该方法会报错
- Reflect.defineProperty(target, propertyKey, attributes)
- 该方法对应于Object.defineProperty,用于定义对象属性,attributes表示属性描述对象
- 该方法可结合Proxy.defineProperty一起使用,proxy.xxx进行拦截,该方法进行赋值
- 第一个参数不是对象,会报错
- Reflect.deleteProperty(obj, name)
- 该方法对应于delete obj[name]
- 该方法返回一个布尔值,当删除失败时返回false,其他时候返回true
- 第一个参数不是对象,该方法会报错
- Reflect.getdOwnPropertyDescriptor(target, propertyKey)
- 该方法对应于Object.getOwnPropertyDescriptor
- 若第一个参数不是对象,则报错,而Object.getOwnPropertyDescriptor则会返回undefined
- Reflect.isExtensible(target)
- 对应于Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展
- 若参数不是对象,该方法会报错,而Object.isExtensible则会返回false,因为非对象本身是不可扩展的
- Reflect.preventExtensions(target)
- 该方法对应于Object.preventExtensions,返回布尔值,表示是否操作成功,用于让一个对象变得不可扩展
- 若参数不是对象,该方法会报错,而Object.xxx在ES5环境中会报错,在ES6环境中返回传入的参数
- Reflect.ownKeys(target)
- 该方法对应于Object.getOwnPropertyNames + Object.getOwnPropertySymbols,返回对象自身的所有属性
- 若第一个参数不是对象,该方法会报错
- Reflect.construct(Target, args)
- 该方法对应于new Target(...args)
- 提供了一种不使用new来调用构造函数的方法
- 第一个参数不是函数,会报错
- Reflect.getPrototypeOf(obj)
- 该方法对应于
obj.__proto__
,对应于Object.getPrototypeOf(obj) - 第一个参数必须是一个对象,而Object.getPrototypeOf第一个参数不是对象会转为一个对象形式,然后再运行
- 该方法对应于
- Reflect.setPrototypeOf(obj, newProto)
- 该方法对应于Object.setPrototypeOf(obj, newProto)
- 该方法返回一个布尔值,表示原型是否设置成功
- 若无法设置目标对象的原型(比如对象禁止扩展),将会返回false
- 若第一个参数不是对象,该方法会报错,而Object.setPrototypeOf返回第一个参数本身
- 若第一个参数为null/undefined,两者都会报错
- Reflect.apply(func, thisArg, args)
- 该方法对应于Function.prototype.apply.call(func, thisArg, args),用于绑定this后执行函数func
应用:实现观察者模式
观察者模式:函数自动观察数据对象,一旦对象有变化,函数就会自动执行
案例:
javascript
const queuedObservers = new Set()
const observe = fn => queuedObservers.add(fn)
const observable = obj => new Proxy(obj, { set })
function set (target, key, value, receiver) {
const result = Reflect.set(target, key, value, receiver)
queuedObservers.forEach(observer => observer(key, value))
return result
}
function print (a, b) {
console.log(a, b)
}
const person = {
name: 'qiujida',
age: 24
}
observe(print)
newPerson = observable(person)
person.name = 'jadeqiu'
// 输出:name jadeqiu
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25