理解reflect
反射,在运行时获得程序或程序集每一个类型的成员和成员信息。 JAVA里程序中一般的对象的类型都是在编译期就确定下来的,而Java反射机制可以动态地创建对象并调用其属性,这样的对象的类型在编译期是未知的。所以我们可以通过反射机制直接创建对象,即使这个对象的类型在编译期是未知的。 js中,就是有一个全局对象,上面挂载了对象的某些特殊方法,这些方法可以通过Reflect.apply这种形式来使用。当然所有方法都可以在Object的原型链中找到的。
用Reflect的好处
- Reflect上面的一些方法并不是专门为对象设计的,比如Reflect.apply方法,它的参数是一个函数,如果使用Object.apply(func)会让人感觉很奇怪。
- 用一个单一的全局对象去存储这些方法,能够保持其它的JavaScript代码的整洁、干净。不然的话,这些方法可能是全局的,或者要通过原型来调用。
- 将一些命令式的操作如delete,in等使用函数来替代,这样做的目的是为了让代码更加好维护,更容易向下兼容;也避免出现更多的保留字。
摘自:ES6 reflect
Reflect的方法
Reflect.apply
Reflect.construct
Reflect.defineProperty
Reflect.deleteProperty
Reflect.enumerate // 废弃的
Reflect.get
Reflect.getOwnPropertyDescriptor
Reflect.getPrototypeOf
Reflect.has
Reflect.isExtensible
Reflect.ownKeys
Reflect.preventExtensions
Reflect.set
Reflect.setPrototypeOf
复制代码
MDN中介绍:reflect
- Reflect.apply()
对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和 Function.prototype.apply() 功能类似。 - Reflect.construct()
对构造函数进行 new 操作,相当于执行 new target(...args)。 - Reflect.defineProperty()
和 Object.defineProperty() 类似。 - Reflect.deleteProperty()
作为函数的delete操作符,相当于执行 delete target[name]。 - Reflect.enumerate()
该方法会返回一个包含有目标对象身上所有可枚举的自身字符串属性以及继承字符串属性的迭代器,for...in 操作遍历到的正是这些属性。 - Reflect.get()
获取对象身上某个属性的值,类似于 target[name]。 - Reflect.getOwnPropertyDescriptor()
类似于 Object.getOwnPropertyDescriptor()。 - Reflect.getPrototypeOf()
类似于 Object.getPrototypeOf()。 - Reflect.has()
判断一个对象是否存在某个属性,和 in 运算符 的功能完全相同。 - Reflect.isExtensible()
类似于 Object.isExtensible(). - Reflect.ownKeys()
返回一个包含所有自身属性(不包含继承属性)的数组。 - Reflect.preventExtensions()
类似于 Object.preventExtensions()。返回一个Boolean。 - Reflect.set()
将值分配给属性的函数。返回一个Boolean,如果更新成功,则返回true。 - Reflect.setPrototypeOf()
类似于 Object.setPrototypeOf()。
Proxy
ES6中将Proxy标准化了,提供了构造函数,例如var p = new Proxy(target, handler); 。
构造函数有两个参数,第一个参数target是要拦截的对象,第二个参数是拦截函数对象。
例子:
var handler = {
get: function(target, name){
return name in target ? target[name] : 'No prop!';
}
};
var p = new Proxy({}, handler);
p.a = 1;
p.b = 2;
console.log(p.a); //1
console.log(p.b); //2
console.log(p.c); //No prop!
复制代码
Proxy的13种拦截行为
- getPrototypeOf / setPrototypeOf 拦截取对象的原型对象的行为
- isExtensible / preventExtensions
- ownKeys / getOwnPropertyDescriptor
- defineProperty / deleteProperty
- get / set / has
- apply / construct
Reflect的实例
on-change是一个可以监听对象或者数组内部变化的小工具,主要使用proxy来实现。 以下是核心代码:
// onChange 即要进行的监听操作
module.exports = (object, onChange) => {
const handler = {
get(target, property, receiver) {
try {
return new Proxy(target[property], handler);
} catch (err) {
return Reflect.get(target, property, receiver);
}
},
defineProperty(target, property, descriptor) {
onChange();
return Reflect.defineProperty(target, property, descriptor);
},
deleteProperty(target, property) {
onChange();
return Reflect.deleteProperty(target, property);
}
};
return new Proxy(object, handler);
};
//一共有三个方法,get defineProperty,deleteProperty
//上面代码可以对数组进行操作就是因为用了proxy,具体的实现在get方法,每一层返回一个proxy,需要注意的是在监听操作这里依然使用的是 es5的 defineProperty 方法。
复制代码