有没有一种方法可以使用JavaScript ES6代理来监视对象方法[重复]

x33g5p2x  于 2023-06-04  发布在  Java
关注(0)|答案(1)|浏览(575)

此问题已在此处有答案

Why is my function proxy not being called in Node?(2个答案)
3年前关闭。
有没有可能,给定以下对象

let target = {
 foo:0,
 result:[],
 bar(){
   //some code
 }
}

然后将所述对象 Package 在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'));

如果我将对象方法 Package 在一个代理中,它会捕获 apply ,但我会丢失对原始对象(this)的引用,因此无法访问结果数组
我还尝试将方法代理嵌套在对象代理中。
有什么想法吗?
CodeSandBox of my actual code
//代理的文档
Proxy MDN
Javascript.info/proxy
//其他问题,关于代理,但不是这个用例
Understanding ES6 javascript proxies

hmae6n7t

hmae6n7t1#

根据质量标准
一个Proxy exotic对象只有一个Call内部方法,如果它的ProxyTarget内部槽的初始值是一个具有Call内部方法的对象。
所以下面的代码会在目标是function的情况下捕获调用

(new Proxy(() => 'hello', { apply: () => console.log('catched') }))() // 'catched

反过来,如果target没有调用方法,则没有代理

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)

edit:NB:不需要每次都创建一个新的代理
在下面的代码中,返回相同的代理大约快两倍

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)
}

相关问题