Indeed write Proxy article a lot, so today I also do not add words, fry two chestnuts.

One, virtual attributes

  const person = {
    name: 'xiaoyun'.province: Jiangsu Province.city: 'Nanjing'
  }
Copy the code

For the above objects, we may need address information (patchwork of provinces and cities), and before that we may do the following:

  • Declare an address property directly on the Person object;
  • When you use the address information, you concatenate it with a Person.

The main drawback of the first method is that it pollutes the original object, while the second method is very inflexible. Now we can do better with a Proxy:

  const enhancePerson = new Proxy(person, {
    get (target, name) {
      switch (name) {
        case 'address':
          return `${target['province']}-${target['city']}`
        default:
          return target[name]
      }
    }
  })
  enhancePerson.address // Nanjing, Jiangsu Province
Copy the code

In this way we can implement the virtual property because it will not be traversed:

  Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
Copy the code

Here’s another point I find easy to miss:

  person === enhancePerson // false
  enhancePerson.city = Suzhou City
  enhancePerson.city === person.city // true
Copy the code

Obviously these are not the same object, but BY changing the city property of enhancePerson I am affecting the city property of the person. This is what we usually ignore. If you don’t set the set method of the Proxy, it will keep the default behavior:

  set (target, propKey, value) {
    target[propKey] = value
  }
Copy the code

Now, some of you might want to think, well, just don’t let it go through? Look at this:

  const person = {
    name: 'xiaoyun'.province: Jiangsu Province.city: 'Nanjing',
    get address () {
      return `The ${this.province}-The ${this.city}`}}const enhancePerson = new Proxy(person, {
    ownKeys (target) {
      return Object.keys(target).filter(item= >item ! = ='address')
    }
  })

  enhancePerson.address // Nanjing, Jiangsu Province
  Object.keys(enhancePerson) // [ 'name', 'province', 'city' ]
Copy the code

Although the above functions have been implemented, there are too many methods intercepted by ownKeys in the Proxy. Therefore, after intercepting ownKeys, some methods will be unavailable, and there are strict requirements on the results returned by intercepting ownKeys:

  • The returned result must be an array
  • The array elements must be of type String or Symbol
  • The result must contain all non-configurable, self-owned properties of the object
  • If the object is not extensible, the result can contain only the properties it owns and no other properties

So pay attention to a lot of interception methods, otherwise it is easy to cause problems.

Tip: The descriptor property for attributes not defined by defineProperty defaults to True, otherwise it defaults to false.

Second, expand the basic operation

When I first came into contact with Python, I was impressed by its List syntax: ARr [1:3]. I used to envy it, but now I can do it myself:

  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['"'] // [3, 4, 5, 6]
Copy the code

Is it 😎? For objects, we can use a similar method:

  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
Copy the code

For those of you who like this article, please follow my subscription account for more content.