一篇文章让你搞懂Reflect和Reflect metadata(JavaScript)
引言
Javascript 里经常看到 Reflect 的使用,但一直搞不明白他和 Object 的区别, 加上在工作中也没有经常用到, 一直处于懵懵懂懂的状态。所以下定决心, 用这篇文章彻彻底底把它搞明白
本文主要涵盖以下4个板块:
- Reflect
- 什么是 Reflect APIs(Reflect与Object的区别)
- 简单的例子: Object vs Reflect
- Reflect简单总结
- Reflect Metadata(npm package)
- 出现背景
- 如何安装
- Reflect Metadata 的用法
- 结语
- 参考文献
Reflect
什么是 Reflect APIs
Reflect是一个内建的对象,用来提供方法去拦截JavaScript的操作。Reflect的所有属性和方法都是静态的。
这个解释是相当抽象的, 用人话来讲就是: Reflect提供了一系列静态方法来对JS对象进行操作
在ES6之前, Javascript一直没有统一的namespace来管理对其他object的操作 比如我们可能使用Object.keys(car)
获取car
这个对象的所有属性
但我们会用property in car
这种形式判断某个属性是否存在于car
. 相信你能看得出来, 这导致了代码上的割裂, 我们为什么不能有一个新的一系列APIs, 支持所有这些对于对象的操作呢?所以这个时候 Javascript推出了Reflect
, 你可以用Reflect.has(car, property)
去判断某个属性存在于car
同时可以用 Reflect.ownKeys(car)
去获取car
的所有属性. 并且所有都是通过调用Reflect里的静态function, 是不是方便和统一很多呢?
以下是Reflect下面的13个static functions以及其对应的JS其他方式的实现:
- Reflect.apply(target, thisArgument, argumentsList)
- 类似于
Function.prototype.apply()
- 类似于
- Reflect.construct(target, argumentsList[, newTarget])
- 类似于
new target(...argumentsList)
- 类似于
- Reflect.defineProperty(target, propertyKey, attributes)
- 类似于
Object.defineProperty()
- 类似于
- Reflect.deleteProperty(target, propertyKey)
- 类似于
delete target[propertyKey]
- 类似于
- Reflect.get(target, propertyKey[, receiver])
- 类似于
target[propertyKey]
- 类似于
- Reflect.getOwnPropertyDescriptor(target, propertyKey)
- 类似于
Object.getOwnPropertyDescriptor()
- 类似于
- Reflect.getPrototypeOf(target)
- 类似于
Object.getPrototypeOf()
- 类似于
- Reflect.has(target, propertyKey)
- 类似于
property in target
- 类似于
- Reflect.isExtensible(target)
- 类似于
Object.isExtensible(target)
- 类似于
- Reflect.ownKeys(target)
- 类似于
Object.keys(target)
- 类似于
- Reflect.preventExtensions(target)
- 类似于
Object.preventExtensions(target)
- 类似于
- Reflect.set(target, propertyKey, value[, receiver])
- 类似于
target[property] = value
- 类似于
- Reflect.setPrototypeOf(target, prototype)
- 类似于
Object.setPrototypeOf(target, prototype)
- 类似于
通过上面的function, 你可以发现, Reflect
里面的所有function在目前JS都能找到对应的实现(Object
, Function
),而现在你不需要去记忆那些复杂的语法,全部都可以用Reflect搞定。JS官方也建议developer能够转而开始使用Reflect 未来关于对象操作的新特性都会添加到Reflect而不是Object。但是为了backwards-compatibility, Object里面已经存在的function也不会被移除
延伸阅读: Comparing Reflect and Object methods
简单的例子: Object vs Reflect
如果去给car对象定义一个新的property, 在Object里面我们需要用到try...catch
去捕捉错误
而Reflect.defineProperty()
则会直接return true or false
代表成功与否
// Object实现
try {
Object.defineProperty(car, name, desc);
// property defined successfully
} catch (e) {
// possible failure (and might accidentally catch the wrong exception)
}
// Reflect实现
if (Reflect.defineProperty(car, name, desc)) {
// success
} else {
// failure
}
Reflect简单总结
Reflect提供了一系列的静态方法(static functions)来操作其他Javascript对象, 其优势在于:
- 函数化所有对象操作
- 更丰富的返回值
- 更统一的命名
- 对于
function apply
更可靠的的支持 -Reflect.apply(f, obj, args)
-
const car = () => { } car.apply = (v) => { console.log('car.apply() runs with'
-