JavaScript 笔记-代理捕获器与反射方法
在代理对象上执行的任何一种操作,只会调用一个捕获处理程序,不存在重复捕获。
只要在代理上调用,所有捕获器都会拦截它们对应的反射 API 操作。
get()
获取属性值的操作会调用 get() 捕获器,对应反射 API 方法 Reflect.get()
1 | |
get() 捕获器无返回值限制,会拦截 proxy.property、proxy[property]、Object.create(proxy)[property] 和 Reflect.get(proxy, property, receiver) 操作。
如果:
target.property不可写且不可配置,处理程序返回的值必须与target.property匹配target.property不可配置且[[Get]]为undefined,处理程序的返回值也必须是undefined
set()
设置属性值的操作会调用 set() 捕获器,对应反射 API 方法 Reflect.set()
1 | |
set() 捕获器返回 true 表示成功;返回 false 表示失败,严格模式会抛出 TypeError。会拦截 proxy.property = value、proxy[property] = value、Object.create(proxy)[property] = value 和 Reflect.set(proxy, property, value, receiver) 操作。
如果:
target.property不可写且不可配置,则不能修改目标属性的值target.property不可配置且[[Set]]特性为undefined,则不能修改目标属性的值
has()
在 in 操作符中会调用 has() 捕获器,对应反射 API 方法 Reflect.has()
1 | |
has() 必须返回表示属性是否存在的布尔值,返回非布尔值会转为布尔值。会拦截 property in proxy、property in Object.create(proxy)、with(proxy) {(property);} 和 Reflect.has(proxy, property) 操作。
如果:
target.property存在且不可配置,处理程序必须返回truetarget.property存在且目标对象不可扩展,处理程序必须返回true
defineProperty()
在 Object.defineProperty() 中会调用 defineProperty() 捕获器,对应反射 API 方法 Reflect.defineProperty()
1 | |
defineProperty() 必须返回表示属性是否存在的布尔值,返回非布尔值会转为布尔值。会拦截 Object.defineProperty(proxy, property, descriptor) 和 Reflect.defineProperty(proxy, property, descriptor) 操作。
如果:
目标对象不可扩展,无法定义属性
目标对象有一个可配置的属性,不能添加同名的不可配置属性
目标对象有一个不可配置的属性,不能添加同名的可配置属性
getOwnPropertyDescriptor()
在 Object.getOwnPropertyDescriptor() 中会调用 getOwnPropertyDescriptor() 捕获器,对应反射 API 方法 Reflect.getOwnPropertyDescriptor()
1 | |
getOwnPropertyDescriptor() 必须返回对象,在属性不存在时返回 undefined。会拦截 Object.getOwnPropertyDescriptor(proxy, property) 和 Reflect.getOwnPropertyDescriptor(proxy, property) 操作。
如果:
target.property存在且不可配置,必须返回一个表示该属性存在的对象target.property存在且可配置,必须返回表示该属性可配置的对象target.property存在且target不可扩展,必须返回一个表示该属性存在的对象target.property不存在且target不可扩展,必须返回undefined表示该属性不存在target.property不存在,不能返回表示该属性可配置的对象
deleteProperty()
在 delete 操作符中会调用 deleteProperty() 捕获器,对应反射 API 方法 Reflect.deleteProperty()
1 | |
deleteProperty() 必须返回表示属性是否存在的布尔值,返回非布尔值会转为布尔值。会拦截 delete proxy.property、delete proxy[property] 和 Reflect.deleteProperty(proxy, property) 操作。
- 如果
target.property存在且不可配置,不能删除这个属性
ownKeys()
在 Object.keys() 及类似方法中会调用 ownKeys() 捕获器,对应反射 API 方法 Reflect.ownKeys()
1 | |
ownKeys() 必须返回包含字符串或符号的可枚举对象。会拦截 Object.getOwnPropertyNames(proxy)、Object.getOwnPropertySymbols(proxy)、Object.keys(proxy) 和 Reflect.ownKeys(proxy) 操作。
必须返回包含
target所有不可配置的自有属性的可枚举对象如果
target不可扩展,返回可枚举对象必须准确包含自有属性键
getPrototypeOf()
在 Object.getPrototypeOf() 中会调用 getPrototypeOf() 捕获器,对应反射 API 方法 Reflect.getPrototypeOf()
1 | |
getPrototypeOf() 必须返回对象或 null。会拦截 Object.getPrototypeOf(proxy)、Reflect.getPrototypeOf(proxy)、proxy.__proto__、Object.prototype.isPrototypeOf(proxy) 和 proxy instanceof Object 操作。
- 如果
target不可扩展,Object.getPrototypeOf(proxy)唯一有效的返回值就是Object.getPrototypeOf(target)的返回值
setPrototypeOf()
在 Object.setPrototypeOf() 中会调用 setPrototypeOf() 捕获器,对应反射 API 方法 Reflect.setPrototypeOf()
1 | |
getPrototypeOf() 必须返回表示原型赋值是否成功的布尔值,返回非布尔值会转为布尔值。会拦截 Object.setPrototypeOf(proxy) 和 Reflect.setPrototypeOf(proxy) 操作。
- 如果
target不可扩展,Object.setPrototypeOf()唯一有效的prototype参数就是Object.getPrototypeOf(target)的返回值
isExtensible()
在 Object.isExtensible() 中会调用 isExtensible() 捕获器,对应反射 API 方法 Reflect.isExtensible()
1 | |
getPrototypeOf() 必须返回表示 target 是否可扩展的布尔值,返回非布尔值会转为布尔值。会拦截 Object.isExtensible(proxy) 和 Reflect.isExtensible(proxy) 操作。
如果:
target可扩展,必须返回truetarget不可扩展,必须返回false
preventExtensions()
在 Object.preventExtensions() 中会调用 preventExtensions() 捕获器,对应反射 API 方法 Reflect.preventExtensions()
1 | |
preventExtensions() 必须返回表示 target 是否已不可扩展的布尔值,返回非布尔值会转为布尔值。会拦截 Object.preventExtensions(proxy) 和 Reflect.preventExtensions(proxy) 操作。
- 如果
Object.isExtensible(proxy)是false,必须返回true
apply()
在调用函数时会调用 apply() 捕获器,对应反射 API 方法 Reflect.apply()
1 | |
apply() 返回值无限制。会拦截 proxy(...argumentsList)、Function.prototype.apply(thisArg, argumentsList)、Function.prototype.call(thisArg, ...argumentsList) 和 Reflect.apply(target, thisArgument, argumentsList) 操作。
target必须是一个函数对象
construt()
在 new 操作符中会调用 construt() 捕获器,对应反射 API 方法 Reflect.construt()
1 | |
construct() 必须返回一个对象。会拦截 new proxy(...argumentsList) 和 Reflect.construct(target, argumentsList, newTarget) 操作。
target必须可用作构造函数