考虑到以下对象,有可能
let target = {
foo:0,
result:[],
bar(){
//some code
}
}
然后将所述对象包装在Proxy()
let handler = {
get(){
// code here
},
apply(){
// code here
}
}
target = new Proxy(target,handler);
捕获到bar()
的呼叫并将结果保存到results:[]
吗?
我已经尝试了
let target = {
called:0,
results:[],
foo(bar){
return bar;
},
}
let handler = {
get(target,prop){
console.log('Get Ran')
return target[prop];
},
apply(target,thisArg,args){
console.log('Apply Ran')
// never runs
}
}
target = new Proxy(target,handler);
target.foo();
此代码错过了[[apply]]但抓住了[[get]] (如果有内存,则对象方法调用将作为两个操作完成,[[get]] [[apply]])
let target = {
called:0,
results:[],
foo(bar){
return bar;
},
}
let handler = {
get(target,prop){
return target[prop];
},
apply(target,thisArg,args){
let product = target.apply(thisArg,args)
return product;
},
}
let prox = new Proxy(target.foo,handler);
console.log(prox('hello'));
如果我改为将对象方法包装在代理中,则会捕获[[apply]] 但我丢失了对原始对象(this)的引用,因此无法访问结果数组
我还尝试过将方法代理嵌套在对象代理内部。
有什么想法吗?
//代理文档
//其他有关代理的问题,但不是本用例
答案 0 :(得分:1)
根据spec
代理异域对象只有在其[[ProxyTarget]]内部插槽的初始值是具有[[Call]]内部方法的对象时,才具有[[Call]]内部方法。
因此,如果目标是function
(new Proxy(() => 'hello', { apply: () => console.log('catched') }))() // 'catched
相反,如果目标没有调用方法,则没有代理
try {
(new Proxy({}, { apply: () => console.log('catched') }))() // throws
} catch (e){ console.log('e', e.message)}
因此提示可能是代理[get],然后代替返回值(作为函数bar
,而是将该值代理以捕获最终的调用
const p = new Proxy(
{ results: [], bar: () => { console.log('rywhite') } }, {
get: (target, prop) => {
if (prop !== 'bar') return target[prop]
return new Proxy (target.bar, {
apply () {
target.results.push('what')
}
})
}
})
p.bar // nothing bud'
p.bar(); console.log('res', p.results)
p.bar(); console.log('res', p.results)
p.bar(); console.log('res', p.results)
编辑:注意:不必每次都创建一个新的代理
在下面的代码中,返回相同的代理大约快两倍
const N = 1e6
{
const target = { results: 0, bar: () => { console.log('rywhite') } }
const p = new Proxy(
target, {
get: (() => {
const barProxy = new Proxy (target.bar, {
apply () {
target.results++
}
})
return (target, prop) => {
if (prop !== 'bar') return target[prop]
return barProxy
}
})()
})
console.time('go')
for (let i = 0; i < N; ++i) { p.bar() }
console.timeEnd('go')
console.log('res', p.results)
}
{
const p = new Proxy(
{ results: 0, bar: () => { console.log('rywhite') } }, {
get: (target, prop) => {
if (prop !== 'bar') return target[prop]
return new Proxy (target.bar, {
apply () {
target.results++
}
})
}
})
console.time('neweverytime')
for (let i = 0; i < N; ++i) { p.bar() }
console.timeEnd('neweverytime')
console.log('res', p.results)
}