ponyfoo.com/articles/es…
很多强类型语言长期以来都有其反射(Reflection)API(如 Python 或 C#),而 JavaScript 作为一种动态语言,则几乎用不着反射。在 ES6 特性里引入的少量扩展之处中,允许开发者用
访问此前的一些语言内部行为就算得上一项。
- Proxy
你可能会反驳,尽管在规范和社区中没有明确那么称呼过,但 JS 在 ES5 中已经有反射特性了。诸如
,
- Array.isArray
, 甚至
- Object.getOwnPropertyDescriptor
这些,在其他语言中都是典型的被列为反射的方法。而内置的
- Object.keys
对象则更进了一步,将这些方法归纳在一起。这很有用,是吧?为什么要用超类
- Reflect
的静态反射方法(如
- Object
或
- getOwnPropertyDescriptor
)呢?毕竟
- create
表示一个基本原型更合适,而不是成为反射方法的仓库。用一个专有接口暴露更多反射方法更有意义。
- Object
和
一样,
- Math
也是不能用
- Reflect
或
- new
调用的静态对象,所有方法也是静态的。ES6
- call
中的陷阱(traps) API 和
- Proxy
中的方法一一对应。
- Reflect
JS 中的反射 API 有一些值得研究的特性。
和 Object 中等价的 Reflect 反射方法同时也提供了更有意义的返回值。比如,Reflect.defineProperty方法返回一个布尔值,表示属性是否被成功定义;而对应的
则返回其首个参数中接收到的对象 -- 这并不是很有用。
- Object.defineProperty
举例来说,以下代码演示了
如何工作:
- Object.defineProperty
- try {
- Object.defineProperty(target, 'foo', { value: 'bar' })
- // yay!
- } catch (e) {
- // oops.
- }
- Reflect.defineProperty
就会感觉自然得多:
- var yay = Reflect.defineProperty(target, 'foo', { value: 'bar' })
- if (yay) {
- // yay!
- } else {
- // oops.
- }
这种方法免去了使用
/
- try
代码块,并使得代码更易维护。
- catch
对于之前只能用关键字做的事情,一些反射方法提供了程序化的替代方案。比如,
等价于
- Reflect.deleteProperty(target, key)
表达式。在 ES6 之前,如果想要调用一个方法达到删除的效果,也只能创建一个专用的工具方法包裹住
- delete target[key]
关键字。
- delete
- var target = { foo: 'bar', baz: 'wat' }
- delete target.foo
- console.log(target)
- // <- { baz: 'wat' }
现在用 ES6 中的
:
- Reflect.deleteProperty
- var target = { foo: 'bar', baz: 'wat' }
- Reflect.deleteProperty(target, 'foo')
- console.log(target)
- // <- { baz: 'wat' }
和
一样, 还有一些其他的方法,提供了更多便利。
- deleteProperty
在 ES5 里,有个难办的事:如何创建一个
并传递任意数量的参数呢?没办法直接实现,而不管怎么弄都会相当麻烦。你不得不创建一个中介对象,借助其将获得的参数变成一个数组;然后对原本的目标对象的构造函数应用这个参数数组,并将结果在中介对象的构造函数中返回。很简单,是不是?- 你说 no 是几个意思?
- new Foo
- var proto = Dominus.prototype
- Applied.prototype = proto
- function Applied (args) {
- return Dominus.apply(this, args)
- }
- function apply (a) {
- return new Applied(a)
- }
使用
实在是简单
- apply
来源: https://juejin.im/post/5a0cf3745188254dd935f342