共计 3068 个字符,预计需要花费 8 分钟才能阅读完成。
最近公司在组织前端团队学习 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",执行 handler
console.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 = 12
if(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);