1、动态属性值
const r1=add[1][2][3]+4//输出10
const r2=add[10][20]+30//输出60
const r3=add[100][200][300]+400//输出1000
柯里化,有参考下文
https://blog.csdn.net/p1967914901/article/details/127621032
add 是对象,通过链式传入属性求和返回结果,咱们会想到代理proxy
Proxy 对象用于创建一个对象的代理,从而实现基本操作的拦截和自定义(如属性查找、赋值、枚举、函数调用等)。
其中 target 是我们要代理的对象,handler 则是以函数作为属性的对象,各属性中的函数分别定义了在执行各种操作时代理 p 的行为。详细介绍请看 MDN 文档。
let add = new Proxy(
{_store:0},
{
get(target, property, receiver) {
target['_store'] += +property
console.log(target['_store'])
return receiver
}
});
add[2][3][10]+3
运行到+3的时候,上面+p报错
其中 target 是目标对象,property 是被获取的属性名,receiver 是 Proxy 或者继承 Proxy 的对象。
let add = new Proxy(
{_store: 0},
{
get(target, property, receiver) {
// console.log(property)//Symbol(Symbol.toPrimitive)
// 遇到 + 的操作,会触发隐式类型转换
if (property === Symbol.toPrimitive) {
return () => {
return target['_store']
}
} else {
target['_store'] += +property
// console.log(target['_store'])
return receiver
}
}
});
console.log(add[2][3][10] + 3)
2、以同步的方式实现事件监听
生产环境不要写,仅做扩展
// 请完成getElement函数让后续程序顺利执行,cssSelector为css选择器
function getElement(cssSelector) {
}
(async () => {
const btn = getElement('button')
while(1) {
await btn.waitClick;//这里的async await在消除事件回调
console.log('按钮被点击了')
}
})()
function getElement(cssSelector) {
const dom = document.querySelector(cssSelector)
return dom
};
//这样写的话相当于题目中 await btn.waitClick=await undefined=await Promise.resolve()
function getElement(cssSelector) {
const dom = document.querySelector(cssSelector)
dom.waitClick=new Promise((resolve)=>{
dom.click=resolve
})
return dom
};
//不太通用,waitClick,waitFocus
<button>以同步的方式实现事件监听</button>
// 请完成getElement函数让后续程序顺利执行
function getElement(cssSelector) {
const dom = document.querySelector(cssSelector)
// 使用Proxy代理dom,拦截所有属性访问,实现事件监听
const proxy = new Proxy(dom, {
get(target, key) {
// 若发现属性非wait开头,则返回原始对象
if (!key.startsWith('wait')) {
return Reflect.get(target, key)
}
// 截取wait后面的字符串并转换为小写,既为事件名称
const eventName = key.replace('wait', '').toLowerCase()
// 返回一个Promise,当事件触发时resolve
return new Promise((resolve) => {
// 事件只需要监听一次即可
dom.addEventListener(eventName, resolve, { once: true })
})
},
})
return proxy
};
(async () => {
const btn = getElement('button')
// while (1) {
// await btn.waitClick
// console.log('按钮被点击了')
// }
// 仅仅监听10次
for (let i = 0; i < 10; i++) {
await btn.waitClick
console.log('按钮被点击了')
}
})()
3、和defineProperty的区别
proxy,能够拦截和重新定义对象的基本操作
对象的基本操作指的是以下等
Object.defineProperty最后就是转换为[[DefineOwnProperty]]使用
假如是个函数的话还会多两个基本操作[[call]] [[construct]]
————————————
proxy能够拦截和重新定义对象的基本操作
defineProperty本身就是个基本操作,只是众多基本操作的其中一个
比方说,以下会报错,这种操作无法重新定义
这一点假如考vue响应式也应该提一嘴
黄色表示vue2重写的数组方法
而vue3使用的是proxy代理,可以拦截对象的所有操作