Proxy、Reflect
从ECMAScript2015开始,JavaScript新增了Proxy和Reflect对象.通过这两个对象你可以拦截并自定义语言原来的操作行为(例如:属性查找、赋值、枚举、函数调用等).借助这两个对象你可以在JavaScript进行元级别进行编程(元编程).
Proxy
Proxy
对象用于定义基本操作的自定义行为(如属性查找、赋值、枚举、函数调用等).
1 | let p = new Proxy(target, handler); |
Proxy
和defineProperty
,写法上很类似.defineProperty
不能对数组进行包装,并且它只有[setter]和[getter]两种对象行为自定义.
1 | let handler = { |
handler
示例
1 | let products = new Proxy({ |
Proxy.revocable(target, handler)
Proxy.revocable(target, handler)
方法可以用来创建一个可撤销的代理对象。
1 | var {proxy, revoke} = Proxy.revocable({}, { |
Reflect
Reflect
是一个内置的对象,它提供拦截 JavaScript 操作的方法。这些方法和Proxy
中handler方法一模一样的.都是有十三种handler方法.
Reflect
不是构造函数,不能在用new
运算符也不能作为函数调用它.Reflect
的所有方法和属性都是静态的.
Reflect
存在的几个目的:
- 将
Object
对象的一些明显属于语言内部的方法(比如Object.defineProperty
),放到Reflect
对象上。现阶段,某些方法同时在Object
和Reflect
对象上部署,未来的新方法将只部署在Reflect
对象上。也就是说,从Reflect
对象上可以拿到语言内部的方法。 - 修改某些
Object
方法的返回结果,让其变得更合理。比如,Object.defineProperty(obj, name, desc)
在无法定义属性时,会抛出一个错误,而Reflect.defineProperty(obj, name, desc)
则会返回false
。 - 让
Object
操作都变成函数行为。某些Object
操作是命令式,比如name in obj
和delete obj[name]
,而Reflect.has(obj, name)
和Reflect.deleteProperty(obj, name)
让它们变成了函数行为。 Reflect
对象的方法与Proxy
对象的方法一一对应,只要是Proxy
对象的方法,就能在Reflect
对象上找到对应的方法。这就让Proxy
对象可以方便地调用对应的Reflect
方法,完成默认行为,作为修改行为的基础。也就是说,不管Proxy
怎么修改默认行为,你总可以在Reflect
上获取默认行为。
方法
Reflect.apply(target, thisArgument, argumentsList)
对一个函数进行调用操作,同时可以传入一个数组作为调用参数。和Function.prototype.apply()
功能类似。Reflect.construct(target, argumentsList[, newTarget])
对构造函数进行new
操作,相当于执行new target(...args)
。Reflect.defineProperty(target, propertyKey, attributes)
和Object.defineProperty()
类似。Reflect.deleteProperty(target, propertyKey)
作为函数的delete
操作符,相当于执行delete target[name]
。Reflect.get(target, propertyKey[, receiver])
获取对象身上某个属性的值,类似于target[name]。
Reflect.getOwnPropertyDescriptor(target, propertyKey)
类似于Object.getOwnPropertyDescriptor()
。Reflect.has(target, propertyKey)
判断一个对象是否存在某个属性,和in
运算符 的功能完全相同。Reflect.ownKeys(target)
返回一个包含所有自身属性(不包含继承属性)的数组。(类似于Object.keys()
, 但不会受enumerable影响
).Reflect.preventExtensions(target)
类似于Object.preventExtensions()
。返回一个Boolean
。Reflect.set(target, propertyKey, value[, receiver])
将值分配给属性的函数。返回一个Boolean
,如果更新成功,则返回true
。Reflect.setPrototypeOf(target, prototype)
类似于Object.setPrototypeOf()
。
参考
https://tc39.es/ecma262/#sec-reflection
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Guide/Meta_programming
https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/Reflect
作者: Fynn
链接: https://fynn90.github.io/2019/09/13/JS_Proxy_and_Reflect/
本文采用知识共享署名-非商业性使用 4.0 国际许可协议进行许可