ES6——Proxy与Reflect
Posted angle-yan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ES6——Proxy与Reflect相关的知识,希望对你有一定的参考价值。
-
Proxy
可以对目标对象的读取、函数等操作进行拦截,然后进行操作处理。它不直接操作函数对象,而是像代理模式,通过对象的代理对对象进行操作,在进行这些操作时,可以增加一些需要的额外操作
-
基本用法
let target = { name: ‘Tom‘, age: 24 } let header = { get: function (target,key) { console.log(‘getting‘+key) return target[key] //注意只能用target[key],不能使用target.key }, set: function (target,key,value) { console.log(‘setting‘+key) target[key] = value } } //生成target的代理对象,对目标对象进行了浅拷贝,因此目标对象和代理对象相互影响 let proxy = new Proxy(target,header) proxy.name //实际执行的是 hander.get console.log(proxy.age = 18) //实际执行的是 hander.set
-
实例方法
-
get(target,propKey,receiver)
拦截读取操作
target: 目标对象
propKey: 属性
receiver: Proxy 对象本身
-
set(target,propKey,value,receiver)
拦截赋值操作
value: 新赋的值
-
apply(target,ctx,args)
拦截函数调用、call 和 apply 操作
ctx: 目标对象上下文
args: 目标对象参数数组
-
has(target,propKey)
拦截 HasProperty 操作,即在判断 target 对象是否存在 propKey 属性,会被该方法拦截。但次方法不拦截
for...in
操作let hanlder = { has: function(target,propKey){ console.log("handle has") return propKey in target } } let exam = {name: ‘Tom‘} let proxy = new Proxy(exam,handler) "name" in proxy //handle //true
-
deleteProperty(target,propKey)
拦截 delete 操作,如果这个方法抛出异常或返回 false ,propKey 属性将无法被 delete 命令删掉
-
construct(target,args)
拦截 new 命令,返回值必须是对象
-
defineProperty(target,propKey,propDesc)
拦截 Object.defineProperty , 若目标不可扩展,增加目标对象上不存在的属性会报错,若属性不可写或不可配置,则不能改变这些属性
-
getOwnPropertyDescriptor(target,propKey)
拦截 Object.getOwnPropertyDescriptor() ,返回值为属性描述对象或者 undefined
let handler = { getOwnPropertyDescriptor: function(target, propKey){ return Object.getOwnPropertyDescriptor(target, propKey); } } let target = {name: "Tom"} let proxy = new Proxy(target, handler) Object.getOwnPropertyDescriptor(proxy, ‘name‘) // {value: "Tom", writable: true, enumerable: true, configurable: true}
-
getPrototypeOf(target)
拦截获取对象原型操作
//包括以下操作 Object.prototype.__proto__ Object.prototype.isPrototypeOf() Object.getPrototypeOf() Reflect.getPrototypeOf() instanceof
返回值必须是对象或 null
-
isExtensible(target)
用于拦截 Object.isExtensible --> 是否是可扩展的
返回值只能是 boolean 值
-
ownKeys(target)
用于拦截对象自身属性的读取操作
//包括以下操作 Object.getOwnPropertyNames() Object.getOwnPropertySymbols() Object.keys() or...in
-
-
-
Reflect
用于获取目标对象行为,与 Object 类似,方法与 Proxy 对应
-
方法
-
Reflect.get(target,name,receiver)
查找并返回 target 对象的 name 属性
let exam = { name: "Tom", age: 24, get info(){ return this.name + this.age; } } Reflect.get(exam, ‘name‘); // "Tom" // 当 target 对象中存在 name 属性的 getter 方法, getter 方法的 this 会绑定 // receiver let receiver = { name: "Jerry", age: 20 } Reflect.get(exam, ‘info‘, receiver); // Jerry20 // 当 name 为不存在于 target 对象的属性时,返回 undefined Reflect.get(exam, ‘birth‘); // undefined // 当 target 不是对象时,会报错 Reflect.get(1, ‘name‘); // TypeError
-
Reflect.set(target,name,value,receiver)
将 target 的 name 属性设置为 value ,返回值为 boolean ,true 表示修改成功, false 表示修改失败。当 target 为不存在的对象时,会报错
-
Reflect.has(obj,name)
name in obj
指令的函数化,用于查找 name 属性在 obj 对象中是否存在。返回值是 boolean 。如果 obj 不是对象会报错 TypeError -
Reflect.deleteProperty(obj,property)
delete obj[property]
的函数化,用于删除 obj 对象的 property 属性,返回值为 boolean 。 -
Reflect.construct(obj,args)
等同于 new target(...args)
-
Reflect.getPrototype(target)
用于读取 obj 的
__proto__
属性。在 obj 不是对象时不会像 Object 一样把 obj 转为对象,而是会报错 -
Reflect.setPrototype(target,newProto)
用于设置目标对象的 prototype
-
Reflect.apply(func,thisArg,args)
等同于
Function.prototype.apply.call(fun,thisArg,args)
。func 表示目标函数;thisArg 表示目标函数绑定的 this 对象;args 表示目标函数调用时传入的参数列表,可以是数组或类似数组的对象。若目标函数无法调用,会抛出 TypeError -
Reflect.defineProperty(target,propKey,attributes)
用于为目标对象定义属性。如果 target 不是对象,会抛出错误
-
Reflect.getOwnPropertyDescriptor(target,propKey)
用于得到 target 对象的 propKey 属性的描述对象
-
Reflect.isExtensible(target)
用于判断 target 对象是否为可扩展。返回值为 boolean
-
Reflect.preventExtensions(target)
用于让 target 对象变为不可扩展。
-
Reflect.ownKeys(target)
用于返回 target 返回的所有属性
-
-
-
组合使用
Reflect 对象的方法和 Proxy 对象的方法是一一对应的。所有 Proxy 对象的方法可以通过调用 Reflect 对象的方法获取默认行为,然后进行额外操作
let exam = { name: "Tom", age: 24 } let handler = { get: function(target, key){ console.log("getting "+key); return Reflect.get(target,key); }, set: function(target, key, value){ console.log("setting "+key+" to "+value) Reflect.set(target, key, value); } } let proxy = new Proxy(exam, handler) proxy.name = "Jerry" proxy.name // setting name to Jerry // getting name // "Jerry"
-
实现观察者模式
// 定义 Set 集合 const queuedObservers = new Set(); // 把观察者函数都放入 Set 集合中 const observe = fn => queuedObservers.add(fn); // observable 返回原始对象的代理,拦截赋值操作 const observable = obj => new Proxy(obj, {set}); function set(target, key, value, receiver) { // 获取对象的赋值操作 const result = Reflect.set(target, key, value, receiver); // 执行所有观察者 queuedObservers.forEach(observer => observer()); // 执行赋值操作 return result; }
-
以上是关于ES6——Proxy与Reflect的主要内容,如果未能解决你的问题,请参考以下文章
@芥末的糖 ---------- ES6---Proxy与Reflect 实现重载(overload)