JS Proxy 與 Object.defineProperty 的區別


Object.defineProperty

vue2.x 以及之前的版本使用 Object.defineProperty 實現數據的雙向綁定,簡單實現下

    let obj = {
      name: '李四',
      address: '上海浦東新區',
      flags: {
        book: {
          page: 153,
          name: 'JS'
        },
        hobby: ['足球', '游戲', '音樂']
      }
    }
    function observer(obj) {
      if (typeof obj == 'object') {
        for (let key in obj) {
          defineReactive(obj, key, obj[key])
        }
      }
    }

    function defineReactive(obj, key, value) {
      Object.defineProperty(obj, key, {
        get() {
          console.log('獲取:' + key)
          return value
        },
        set(val) {
          observer(val)
          console.log(key + "-數據改變了")
          value = val
        }
      })
    }

    observer(obj)

  

問題1.刪除或者增加對象屬性無法監聽到

 

 

 

 

問題2.數組的變化無法監聽到

 

 

 

問題3. 由於是使用遞歸遍歷對象,使用 Object.defineProperty 劫持對象的屬性,如果遍歷的對象層級比較深,花的時間比較久,甚至有性能的問題

 

proxy 

 對象用於定義基本操作的自定義行為

簡單來說就是,可以在對目標對象設置一層攔截。無論對目標對象進行什么操作,都要經過這層攔截

 

let obj = {
      name: '李四',
      address: '上海浦東新區',
      flags: {
        book: {
          page: 153,
          name: 'JS'
        },
        hobby: ['足球', '游戲', '音樂']
      }
    }


    function observerProxy(obj) {
      const handler = {
        get(target, key, receiver) {
          console.log('獲取:' + key) // 如果是對象,就遞歸添加 proxy 攔截
          if (typeof target[key] === 'object' && target[key] !== null) {
            return new Proxy(target[key], handler)
          }
          return Reflect.get(target, key, receiver)
        },
        set(target, key, value, receiver) {
          console.log('設置:' + key) // 如果是對象,就遞歸添加 proxy 攔截
          return Reflect.set(target, key, value, receiver)
        }
      }
      return new Proxy(obj, handler)
    }

    let newObj = observerProxy(obj)

 

1.Object.defineProperty 攔截的是對象的屬性,會改變原對象。proxy 是攔截整個對象,通過 new 生成一個新對象,不會改變原對象。

2.proxy 的攔截方式,除了上面的 get 和 set ,還有 11 種。選擇的方式很多 Proxy,也可以監聽一些 Object.defineProperty 監聽不到的操作,比如監聽數組,監聽對象屬性的新增,刪除等。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM