摘自知乎:https://zhuanlan.zhihu.com/p/92700557
在看菜鸟ES6看到 Reflect.ownKeys(syObject); 看的不是很懂。
前言
今天我们要聊的是一个比较生僻的概念-反射,在JS中至少我之前没听过,直到在后来的一个项目中看到TL写的代码才知道还有这么一个概念。可能Pyhton的童鞋会反驳,因为这个概念在他们的语言中是经常被使用的,无奈偶是C语言的。。。。
在国内的技术文章中你去搜索"JS 反射"得到的大部分的内容都是在说“利用JS的for(…in…)语句实现反射机制”,但其实反射机制在如今的ES6中可以得到更大的延伸以及运用的,这个在后续会讲解。不过这些文章都用一句比较通俗的话来说什么叫反射机制:
反射机制指的是程序在运行时能够获取自身的信息
明白这句话对后面的应用会受益很多。
1 JS的反射对象
反射机制我们在前言中提过了,那么在ES6中JS提供了一个叫做Reflect的对象。
在MDN上的反射对象是这样定义的:
Reflect是一个内建的对象,用来提供方法去拦截JavaScript的操作。Reflect不是一个函数对象,所以它是不可构造的,也就是说它不是一个构造器,你不能通过`new`操作符去新建或者将其作为一个函数去调用Reflect对象。Reflect的所有属性和方法都是静态的。
可是MDN并没有说明为什么需要这么一个对象?
1.1 为什么需要Reflect对象
因为我们刚才说过了,利用JS的for..in可以实现,还有比如Array.isArray
/Object.getOwnPropertyDescriptor
,或者甚至Object.keys
都是可以归类到反射这一类中。那么ECMA为什么还要这个呢?
当然是为了让JS更加强大了,相当于说提供Reflect对象将这些能够实现反射机制的方法都归结于一个地方并且做了简化,保持JS的简单。于是我们再也不需要调用Object
对象,然后写上很多的代码。
比如:
var myObject = Object.create(null) // 此时myObject并没有继承Object这个原型的任何方法,因此有:
myObject.hasOwnProperty === undefined // 此时myObject是没有hasOwnProperty这个方法,那么我们要如何使用呢?如下:
Object.prototype.hasOwnProperty.call(myObject, 'foo') // 是不是很恐怖,写这么一大串的代码!!!!
而如果使用Reflect对象呢?
var myObject = Object.create(null)
Reflect.ownKeys(myObject)
再比如当你对象里有Symbol的时候,如何遍历对象的keys?
var s = Symbol('foo');
var k = 'bar';
var o = { [s]: 1, [k]: 1 };
// getOwnPropertyNames获取到String类型的key,getOwnPropertySymbols获取到Symbol类型的key
var keys = Object.getOwnPropertyNames(o).concat(Object.getOwnPropertySymbols(o));
而使用Reflect的话:
var s = Symbol('foo');
var k = 'bar';
var o = { [s]: 1, [k]: 1 };
Reflect.ownKeys(o)
相比较之下,Reflect对象的作用凸显出来了吧?
另外Reflect还提供了一些Object对象没有的方法,比如Reflect.apply
。