概述大家好,我是一碗周,一个不想被喝(内卷)的前端。如果写的文章有幸可以得到你的青睐,万分有幸~
在ES2015的标准中新增了一个Proxy,用于修改某些 *** 作的默认行为,等同于在语言层面作出的修改,所以说这是属于一种元编程 ,(meta programming),即对编程语言进行编程。
Proxy对象用于创建一个对象的“代理”,从而实现基本能 *** 作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
通俗一点的解释就是,房子比作原始对象,中介比作Proxy,我们租房可以直接找原始房源,也可以通过中介,中介在其中可以屏蔽原始信息。
Proxy的语法结构如下所示:
const p = new Proxy(target, handler)
参数说明:
-
target:要使用Proxy 代理的目标对象(可以是任何类型的对象,包括原生数组,函数,甚至另一个代理)。
-
handler:这个参数是一个配置对象,对于每一个被代理的 *** 作,都需要提供一个对应的处理函数。
Proxy可拦截的 *** 作如下表所示:
以上就是Proxy可拦截的所有 *** 作。
Proxy实例的方法下面我们就对上面那些拦截 *** 作进行逐一演示
get()get方法用于拦截某个属性的读取 *** 作,该方法可以接受是三个参数,分别是目标对象、被获取的属性名和Proxy实例本身(可选)。
下面是对get的简单用法,如果我们访问一个对象中未定义的属性,可以通过get使其抛出一个异常。
const person = { name: '一碗周' } const proxy = new Proxy(person, { get (target, propKey, receiver) { if (propKey in target) { return target[propKey] } else { throw new ReferenceError(`属性:${propKey} 不存在`) } } }) proxy.name // 一碗周 proxy.hobby // 抛出异常
get方法是可以继承的,看下面这段代码
const person = { name: '一碗周' } const proxy = new Proxy(person, { get (target, properKey, receiver) { console.log(`获取${properKey}属性的值:${target[properKey]}`) return target[properKey] } }) // 通过proxy创建一个新的对象 const obj = Object.create(proxy) obj.name // 获取name属性的值:一碗周
上面代码中,拦截 *** 作定义在Prototype对象上面,所以如果读取obj对象继承的属性时,拦截会生效。
我们还可以通过get方法去实现数据读取负数的索引,实现代码如下:
function createArray (...elements) { let handler = { get (target, properKey, receiver) { // 1. 缓存传入的索引值 let index = Number(properKey) if (index < 0) { // 例如 target 的长度为7,传递的 index 为 -1, 最后的 properKey 等于 6 即最后一项 properKey = String(target.length + index) } return Reflect.get(target, properKey, receiver) } } let target = [] target.push(...elements) return new Proxy(target, handler) } const arr = createArray(1, 2, 3, 4, 5) console.log(arr[-1]) // 5
值得注意的是,如果一个属性是不可配置(configurable)且不可写(writable),则Proxy不能修改该属性,否则就会抛出异常。
set()set方法用于拦截某个对象的修改 *** 作,该方法接受四个参数分别是目标对象、被获取的属性名、修改后的值和Proxy实例本身(可选)。
下面这个例子就规定了修改某个属性必须是某个类型的值,否则就会抛出异常
const person = { name: '一碗周' } // 1. 根据指定条件修改name属性 const proxy = new Proxy(person, { set (target, propKey, value, receiver) { // 规定修改name属性只能修改为一个字符串,否则就会抛出异常 if (propKey === 'name' && typeof value !== "string") { throw new TypeError('修改的name并不是一个string') } target[propKey] = value return true } }) // proxy.name = 1 // 抛出异常 proxy.name = '一碗周' // 修改成功
我们该可以利用set方法进行数据绑定,如果对象发生改变,就自动更新我们的DOM。
示例代码如下:
通过set自动更新dom 欢迎分享,转载请注明来源:内存溢出
评论列表(0条)