为了账号安全,请及时绑定邮箱和手机立即绑定

有没有办法使用 Javascript ES6 代理来监视对象方法

有没有办法使用 Javascript ES6 代理来监视对象方法

慕妹3146593 2022-07-21 10:29:04
有没有可能,给定以下对象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 )的引用,因此无法访问结果数组我还尝试将方法代理嵌套在对象代理中。有什么想法吗 ?
查看完整描述

1 回答

?
墨色风雨

TA贡献1853条经验 获得超6个赞

根据规格


如果其 [[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)

}


查看完整回答
反对 回复 2022-07-21
  • 1 回答
  • 0 关注
  • 98 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号