- A+
所属分类:Web前端
反射机制的定义
反射通常指在程序在运行时能够获取自身的信息。
静态语言反射
在java中使用反射的一个例子
Class<?> clazz = Class.forName("com.netease.main.Person"): Method[] methods = clazz.getMethods():
JavaScript 反射
假设有一个对象obj,我们不知道他的内部结构和Api。这个时候我们通过某种机制获取一个对象的内部结构,这种机制就叫做反射。
我们可以看下javaScript中的几个例子
for(let p in window) { console.log(p) } // 了解了window内部结构后,我们可以使用window内部的属性,我们尝试调用它的方法 window['open']('http://www.baidu.com')
// 使用Object.keys方法获取对象的内部结构: let obj = { id: 1, name: 'xxx', test: function test() { console.log('test') } } // 输出结果: console.log(Object.keys(obj))
以上我们通过几个例子基本了解了什么是反射。
Reflect
Reflect是一个内置对象,它提供拦截JavaScript操作的方法。Reflect没有构造函数,不能使用‘new’运算符去新建,也不能将其作为一个函数去调用。Reflect的所有属性和方法都是静态的(类似Math对象)。
为什么需要Reflect对象?
- 把实现反射机制的方法重新归结在一起并且简化操作,保持JS语意清晰和语法简单。
let key1 = 'id', key2 = Symbol.for('name'), obj = { [key1]: 1, [key2]: 'xxx' }; let keys = Object.getOwnPropertyNames(obj).concat(Object.getOwnPropertySymbols(obj)) // 使用Reflect 获取所有keys let reflectKeys = Reflect.ownKeys(obj)
- 补充了一些Object对象没有的方法,比如Reflect.apply。
function fn(...rest) { console.log(rest); console.log('test:' + this.name) } fn.apply = null; fn.apply(1,2,3); // TypeError: fn.apply is not a function Function.prototype.apply.call(fn, {name: 'xxx'}) // [] test: name Reflect.apply(fn, {name: 'xxx'},[1,2,3]);
- 让Object操作都变成函数行为,比如使用Reflect.has(obj,name)替换name in obj。
let obj1 = { name: 'xxx'}; if ('name' in obj1) { console.log('test ok') } let obj2 = { name: 'xxx'}; if(Reflect.has(obj2, 'id')) { console.log('test ok') }
Reflect.apply()
对于一个函数进行调用操作,同时可以传入一个数组作为调用参数。
Reflect.apply(target,thisArgument,argumentsList)
Reflect.construct()
对构造函数进行new 操作,相当于执行new target(...args)。
Reflect.construct(target,argumentsList[,newTarget])
Reflect.defineProperty()
定义对象的一个属性。attributes为属性描述
Reflect.defineProperty(target,property,attributes)
Reflect.deleteProperty()
删除对象的一个属性。
Reflect.deleteProperty(target,property)
Reflect.get()
查找并返回对象的属性值。
Reflect.get(target, property[, receiver])
可以看个例子
// 缺省receiver let obj = { a: 1, b: 2, get c() { return this.a + this.b } } console.log(Reflect.get(obj, 'a')) // 1 console.log(Reflect.get(obj, 'b')) // 2 console.log(Reflect.get(obj, 'c')) // 3 // 加上receiver let obj1 = { a: 1, b: 2, get c() { return this.a + this.b } } let receiver = { a: 4, b: 4, } console.log(Reflect.get(obj1, 'a',receiver)) // 1 console.log(Reflect.get(obj1, 'b',receiver)) // 2 console.log(Reflect.get(obj1, 'c',receiver)) // 8
Reflect.set()
设置对象的属性值
Reflect.set(target, property, value[, receiver])
// 缺省receiver let obj = { name: 'test', } console.log(obj.name); // test Reflect.set(obj, 'name', 'xxx') console.log(obj.name) // xxx
// 加上reveiver let obj = { name: 'test', set nickname(value) { return this.name = value } } let receiver = { name: 'test' } console.log(obj.name); // test console.log(receiver.name); // test Reflect.set(obj, 'nickname', 'xxx', receiver); console.log(obj.name); // test console.log(receiver.name); // xxx
Reflect.getOwnPropertyDescriptor()
查找并返回对象的属性描述符。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
Reflect.getPrototypeOf()
返回指定对象的原型,读取对象的__proto__属性。
Reflect.getPrototypeOf(target)
Reflect.setPrototypeOf()
设置指定对象的原型。
Reflect.setPrototypeOf(target,prototype)
Reflect.has()
判断obj是否有某个属性。
Reflect.has(target,prototype)
Reflect.isExtensible()
判断一个对象是否可扩展
Reflect.isExtensible(target)
Reflect.preventExtensions()
让对象变为不可扩展。
Reflect.preventExtensions(target)
Reflect.ownKeys()
返回要给包含所有自身属性(不包含继承属性)的数组。
Reflect.ownKeys(target)