js中已经有object了,为什么还需要Reflect 反射

147 阅读2分钟

在JavaScript中,Object对象已经提供了一些反射的能力,例如Object.keys()Object.defineProperty()等方法,可以获取对象的属性,定义属性等。然而,Reflect反射对象的出现,是为了更好地支持和完善JavaScript的反射能力。

首先,Reflect提供了一些Object没有的功能。例如,Object.keys()不能获取对象的Symbol属性,而Reflect.ownKeys()可以。这使得Reflect的API在兼容性和功能性上更强大。例如:

const s = Symbol('foo');
const obj = {
 a: 1,
 b: 'string',
 [s]: 1,
};

// 使用Object.keys()获取对象的key
Object.keys(obj);
// ['a', 'b']

// 使用Reflect.ownKeys()获取对象的key
Reflect.ownKeys(obj);
// ['a', 'b', Symbol(foo)]

 

12

其次,Reflect对于行为表现上也有所不同。例如,Object.defineProperty()在执行失败时会抛出一个错误,这可能会打断进程,我们需要使用try...catch来保证代码执行。而Reflect.defineProperty()则不会抛出错误,而是在失败时返回false。例如:

// 使用Object.defineProperty()定义属性
try {
 Object.defineProperty(obj, prop, attr);
 // success do some other logic
} catch(e) {
 // fail
}

// 使用Reflect.defineProperty()定义属性
if (Reflect.defineProperty(obj, prop, attr)) {
 // success do some other logic
} else {
 // fail
}

 

2

最后,Reflect的出现,使得JavaScript的反射能力得以完善,有了相同的使用习惯,利于延续正常的编程逻辑。

补充:

在JavaScript中,反射是在程序运行中获取和动态操作自身内容的一项技术。Reflect是一个内置对象,提供了一系列操作对象的方法,这些方法都是静态的(类似Math),使用Reflect的方法可以做一些对象的基本操作。例如,Reflect.has(target, propertyKey)可以检测一个对象是否存在特定属性。1

const duck = {
 name: 'Maurice',
 color: 'white',
 greeting: function() {
   console.log(`Quaaaack! My name is ${this.name}`);
 }
}

Reflect.has(duck, 'color'); // true
Reflect.has(duck, 'haircut'); // false

 

Reflect提供的是一整套反射能力API,它们的调用方式,参数和返回值都是统一风格的,我们可以使用Reflect写出更优雅的反射代码。在Reflect库出现之前我们只是利用分散的API完成一些动态编程的事情,Reflect使得反射真正成为一种标准化能力。2

Reflect对象上面的方法和Proxy上面都是一一对应的,参数也是完全相同的,因此在Proxy中可以使用Reflect来操作对象。2

new Proxy(obj, {
 set(...args) {
   return Reflect.set(...args);
 },
 get(...args) {
   return Reflect.get(...args);
 },
 deleteProperty(...args) {
   return Reflect.deleteProperty(...args);
 },
 has(...args) {
   return Reflect.has(...args);
 }
});

 

Reflect更强大之处在于它的元编程能力,有一个metadata的提案可以通过Reflect添加元数据信息,使用元数据编程能够更方便进行框架开发。2