快來圍觀一下JavaScript的Proxy

的確寫Proxy文章不少,那麼今天我也不湊字數了,炒兩個栗子吧。數組

1、虛擬屬性

const person = {
    name: 'xiaoyun',
    province: '江蘇省',
    city: '南京市'
  }
複製代碼

對於上述對象,咱們可能須要地址信息(由省市拼接而成),在此以前咱們可能會採起下列方式:ui

  • 直接在person對象上聲明一個address屬性;
  • 當用到address信息時,再經過person拼接。

第一個方法的主要弊端是污染了原有的對象,而第二種方法就很不靈活。如今咱們能夠經過Proxy實現比較好的效果:this

const enhancePerson = new Proxy(person, {
    get (target, name) {
      switch (name) {
        case 'address':
          return `${target['province']}-${target['city']}`
        default:
          return target[name]
      }
    }
  })
  enhancePerson.address // 江蘇省-南京市
複製代碼

經過這種方式咱們就能夠實現虛擬屬性了,由於它不會被遍歷出來:spa

Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
複製代碼

這裏還有一個我以爲比較容易忽略的點:code

person === enhancePerson // false
  enhancePerson.city = '蘇州市'
  enhancePerson.city === person.city // true
複製代碼

顯然這兩個並非同一個對象,可是我經過改變enhancePerson的city屬性卻影響到了person的city屬性,這就是咱們一般會忽略掉的,若是你不設置Proxy的set方法,它會保持默認行爲:cdn

set (target, propKey, value) {
    target[propKey] = value
  }
複製代碼

可能有些同窗會想不就是不讓它遍歷出來嗎?看這招:對象

const person = {
    name: 'xiaoyun',
    province: '江蘇省',
    city: '南京市',
    get address () {
      return `${this.province}-${this.city}`
    }
  }

  const enhancePerson = new Proxy(person, {
    ownKeys (target) {
      return Object.keys(target).filter(item => item !== 'address')
    }
  })

  enhancePerson.address // 江蘇省-南京市
  Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
複製代碼

雖然是實現了上述的功能,可是Proxy中的ownKeys攔截的方法太多,因此咱們攔截ownKeys以後,會致使某些方法沒法使用,而且攔截ownKeys返回的結果也有嚴格的要求:ip

  • 返回的結果必須是一個數組
  • 而且數組的元素必須是String或者Symbol類型
  • 結果必須包含對象的全部不可配置、自身擁有的屬性
  • 若是對象不能擴展,則結果只能包含自身擁有的屬性,不能含有其餘屬性

因此在攔截方法注意點不少,否則很容易出現問題。ci

Tip: 未經過defineProperty定義的屬性的描述器屬性默認爲true,不然默認爲false。get

2、擴展基本操做

當我第一次接觸Python時,比較有印象的就是它的List的一個語法: arr[1:3],之前只有羨慕的份,如今徹底能夠本身擼一個:

const arr = [1, 2, 3, 4, 5, 6, 7, 8]

  const list = new Proxy(arr, {
    get (target, name) {
      if (name.includes(':')) {
        const indexs = name.split(':')
        return target.slice(indexs[0], indexs[1])
      }
      return target[name]
    }
  })

  list['2:6'] // [ 3, 4, 5, 6 ]
複製代碼

是否是😎,對於對象,咱們一樣能夠採用相似的方法:

const obj = {
    a: {
      b: {
        c: 'xiaoyun'
      }
    }
  }

  const obj1 = new Proxy(obj, {
    get (target, name) {
      const keys = name.split('.')
      return keys.reduce((pre, next) => {
        if (pre !== null && pre !== undefined) {
          pre = pre[next]
        }
        return pre
      }, target)
    }
  })
  obj1['a.b.c'] // xiaoyun
複製代碼

    喜歡本文的小夥伴們,歡迎關注個人訂閱號超愛敲代碼,查看更多內容.

相關文章
相關標籤/搜索