亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

有沒有辦法使用 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 關注
  • 88 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號