什么是Reflect
为什要叫做反射?因为它能做的事情,和其他语言(Java、python等)中的反射很相似。其他语言中都叫做反射了,那就共鸣。
Reflect对象与Proxy对象一样,也是 ES6 为了操作对象而提供的新 API。Reflect对象的设计目的有这样几个。
-
将Object对象的一些明显属于语言内部的方法(比如Object.defineProperty),放到Reflect对象上。现阶段,某些方法同时在Object和Reflect对象上部署,未来的新方法将只部署在Reflect对象上。也就是说,从Reflect对象上可以拿到语言内部的方法。
-
修改某些Object方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)则会返回false。
实现反射
let animal = {name: "dog",age: 3}
Reflect.get(animal, "name") // 传参为:对象, 属性名
// 等同于:
animal.name let say = function (type, sound) {console.log(`${type}的叫声是${sound}`)
}
Reflect.apply(say, null, ["猫", "喵喵"]) // 传参为:函数, this指向, 实参列表
// 等同于:
say("猫", "喵喵")
经过以上代码我们深刻的发现Reflect好像没什么用,非要说些什么的话,他把我们以前的基本操作(比如:obj.name)用调用函数的方式实现了一遍。对了这就是它的意义:减少JS语言魔法,让代码更加纯粹。
静态方法
Reflect对象一共有 13 个静态方法。
方法名 | 作用 |
---|---|
Reflect.apply(target, thisArg, args) | Reflect.apply方法等同于Function.prototype.apply.call(func, thisArg, args),用于绑定this对象后执行给定函数 |
Reflect.construct(target, args) | Reflect.construct方法等同于new target(…args),这提供了一种不使用new,来调用构造函数的方法 |
Reflect.get(target, name, receiver) | Reflect.get方法查找并返回target对象的name属性,如果没有该属性,则返回undefined |
Reflect.set(target, name, value, receiver) | Reflect.set方法设置target对象的name属性等于value。 |
Reflect.defineProperty(target, name, desc) | Reflect.defineProperty方法基本等同于Object.defineProperty,用来为对象定义属性。未来,后者会被逐渐废除,请从现在开始就使用Reflect.defineProperty代替它 |
Reflect.deleteProperty(target, name) | Reflect.deleteProperty方法等同于delete obj[name],用于删除对象的属性 |
Reflect.has(target, name) | Reflect.has方法对应name in obj里面的in运算符 |
Reflect.ownKeys(target) | Reflect.ownKeys方法用于返回对象的所有属性,基本等同于Object.getOwnPropertyNames与Object.getOwnPropertySymbols之和 |
Reflect.isExtensible(target) | Reflect.isExtensible方法对应Object.isExtensible,返回一个布尔值,表示当前对象是否可扩展 |
Reflect.preventExtensions(target) | Reflect.preventExtensions对应Object.preventExtensions方法,用于让一个对象变为不可扩展。它返回一个布尔值,表示是否操作成功 |
Reflect.getOwnPropertyDescriptor(target, name) | Reflect.getOwnPropertyDescriptor基本等同于Object.getOwnPropertyDescriptor,用于得到指定属性的描述对象,将来会替代掉后者 |
Reflect.getPrototypeOf(target) | Reflect.getPrototypeOf方法用于读取对象的__proto__属性,对应Object.getPrototypeOf(obj) |
Reflect.setPrototypeOf(target, prototype) | Reflect.setPrototypeOf方法用于设置目标对象的原型(prototype),对应Object.setPrototypeOf(obj, newProto)方法。它返回一个布尔值,表示是否设置成功 |
上面这些方法的作用,大部分与Object对象的同名方法的作用都是相同的,而且它与Proxy对象的方法是一一对应的。
es6观察者模式
function observer(target) {const div = document.getElementById("container");const proxy = new Proxy(target, {set(target, prop, value) {Reflect.set(target, prop, value)render()},get(target, prop) {return Reflect.get(target, prop)}})render()function render() {let html = "";for (const prop of Object.keys(target)) {html += `<p><span>${prop}:</span><span>${target[prop]}</span></p>`}div.innerHTML = html;}return proxy;}const target = {a: 1,b: 2}const obj = observer(target);target.a = 1000; //目标函数不改变,让代理函数obj干obj.a = 5000;obj.c = 8; //代理配置可以改变属性