最近公司在组织前端团队学习JavaScript高级程序设计(第四版)。这两天把第九章看完了,以下是精简版的学习笔记:
本章要点:
- proxy是代理的意思, 能够通过 构造函数 Proxy,给指标对象targetObj创立一个代理对象
- 对代理对象执行操作,会走handler里的办法,对源对象执行操作,不会
- 代理能够捕捉13中不同的根底api,handler中可定义多个捕捉办法
- 是一个全局的Reflect对象,所有捕捉的办法都有对应的Reflect api办法。它与捕捉器拦挡的办法同名、行为雷同。
- Reflect api 不限于捕捉处理程序handler,也可用在解决一般对象上
- 大多数Reflect api在Object上有对应的办法
- 有了Reflect后,能够不便写捕捉器
- 代理模式的几种利用
proxy
what?(Proxy是什么?)
proxy是代理的意思, 能够通过 构造函数 Proxy,给指标对象targetObj创立一个代理对象。
const proxyObj = new Proxy(targetObj, handlerObj)
能够给对象obj创立一个代理。
why?(为什么用Proxy?)
当对代理对象进行一些对象操作时,会先执行代理中handlerObj对象定义的办法。
比方:
get( ) // 取对象属性set( ) // 往对象中增加属性
how?(怎么用Proxy?)
对代理对象执行操作,会走handler里的办法
对源对象执行操作,不会走handler里的办法
const target = {foo: "bar"}const handler = { get(target, prop, receiver){ // get()是一个捕捉器,其参数别离代表:指标对象、指标属性、代理对象。每个捕捉器入参不同。 return "handle override" }}const proxyObj = new Proxy(target,handler)console.log(proxyObj.foo) // "handle override",执行handlerconsole.log(target.foo) // "bar",没有执行handler
Reflect
what?(Reflect是什么?)
是一个全局的Reflect对象,所有捕捉的办法都有对应的Reflect api办法。它与捕捉器拦挡的办法同名、行为雷同。
Reflect api 不限于捕捉处理程序handler
大多数Reflect api在Object上有对应的办法。
why?(为什么用Reflect?)
有了Reflect后,能够不便写捕捉器。
看例子:
const target = {foo: "bar"}const handler = { get(target, prop, receiver){ return Reflect.get(...arguments) }}const proxyObj = new Proxy(target,handler)
Reflect api会提供一些状态标记。
Reflect.set() ,Reflect.defineProperty()会返回布尔值。
Reflect api可利用一等函数替换操作符。Reflect.has( )
const obj = {name: "cc"}const target = Object.create(obj)target.age = 12if(Reflect.has(target, "name")) { // 亲测和对象的in操作符成果雷同,都能够获取对象原型链上的属性 console.log("wow, I have!")}
how?(怎么用Reflect?)
以上,写捕捉器的时候能够用,利用它的返回值,在对象上也能够用
代理捕捉器和对应的反射办法
代理能够捕捉13中不同的根底api。
get() 获取属性时
set() 设置属性值
has() 对象执行in操作时
defineProperty( )
getOwnPropertyDescriptor()
deleteProperty()
ownKeys()
getPrototypeOf()
setPropotypeOf()
isExtensible()
preentExtensions()
apply()
construct()
代理模式的几种利用
- 跟踪属性拜访
通过捕捉get、set 和has 等操作,能够晓得对象属性什么时候被拜访、被查问。
- 暗藏属性
- 属性验证
set()外面写捕捉器,验证对象的赋值操作是否非法
例子:
setObjDataEmpty = (paramObj) => { const proxy = new Proxy(paramObj, { set(target, prop) { const oldVal = target[prop] if(typeof oldVal === "string") { // 字符串,间接赋值 return Reflect.set(...arguments) }else if(Array.isArray(oldVal)){ return Reflect.set(target, prop, []) // 数组,置空 }else{ return false // 都不是,赋值失败 } } }) Object.keys(proxy).forEach(key => { proxy[key] = "" }) return proxy}
- 函数和构造函数的参数验证
consructor = () => { class SetId { constructor(id) { this.id = id } } const pSetId = new Proxy(SetId, { construct(target, argumentList) { if(argumentList[0] === undefined) { throw("oh, you must put id!") }else{ return Reflect.construct(...arguments) } } }) const id1 = new pSetId("1") console.log(id1) // {id: '1'} const id2 = new pSetId() // Uncaught oh, you must put id! console.log(id2) }
- 数据绑定与可察看对象
const userList = []; class User { constructor(name) { this.name = name; } } const proxy = new Proxy(User, { construct() { const newUser = Reflect.construct(...arguments); userList.push(newUser); return newUser; } }); new proxy('John'); new proxy('Jacob'); new proxy('Jingleheimerschmidt'); console.log(userList);