快速理解ES6中的代理Proxy和反射Reflect

代理和反射是ES6中新增的API, 理解两个API用处很多,比如vue中数据绑定实现的原理是调用Object.defineProperty,而Proxy其实就是Object.defineProperty的语法糖,传言未来发布的Vue3.0也会使用Proxy+MutationObserver来重写数据绑定的底层实现,可见这个API作用还是大大的,下面介绍两个简单的例子,来让你快速的理解这两个API
Proxy:
个人理解:不直接操作对象,而是通过操作对象的代理对象来操作对象,什么意思,看下面代码,我们获取age值的时候不是直接通过user.age获取,而是先new一个user的代理对象p,通过这个p去获取age,好处是可以在设置和获取属性时进行一些额外的操作,比较类似于装饰器的作用

var user= {
  name: 'iwen',
  age: 18
}
var p = new Proxy(user, {
  get(target, key) {
    console.log(`get ${key}`)
    return target[key]
  },
  set(target, key, val) {
    console.log(`set ${key}`)
    target[key] = val
  }
})
p.age // get age
p.age = 20 // set age

在刚开始学习vue的时候一般都会有这样一个疑问,data明明是一个函数,理论上应该是this.data().[key] 来获取data中的数据,但是实际上却是this[key]获取的,这个是怎么实现的,其实只要我们把上面的代码稍微改造一下就明白了

var options = {
  data() {
    return {
      name: 'iwen',
      age: 18
    }
  }
}
var vm = new Proxy(options, {
  get(target, key) {
    return target.data()[key]
  },
  set(target, key, val) {
    target.data()[key] = val
  }
})
vm.age

Reflect
个人理解,其实就将换一种更加优雅的方式来操作对象。
比如判断对象中是否有某个属性

'age' in obj // 传统做法
Reflect.has(obj, 'age') // Reflect做法

比如apply使用(bar为一个函数)

bar.apply(obj, 'iwen') // 传统做法
Reflect.apply(bar, obj, [1, 2, 3]) // Reflect做法 

下面做一个小练习,来加深对这个API的理解,比如项目中window上绑定了很多事件,在不修改项目原有代码的基础上如何获取window上所有绑定的事件?
你可以先自己思考一下,下面是答案

/**
 * @desc 获取window上所有绑定的事件
 */
var getAllWindowEvent = function (w) {
  w.listLenster = new Set()
  var _cache = w.addEventListener
  var handler = {
    apply(target, thisBindding, args) {
      listLenster.add(args[0])
      Reflect.apply(_cache, w, args)
    }
  }
  w.addEventListener = new Proxy((event, fn) => {}, handler)
}
getAllWindowEvent(window)

// 这里的window.addEventListener已经是是代理对象了
window.addEventListener('click', function() {
  console.log('click')
})
window.addEventListener('resize', function() {
  console.log('resize')
})
console.log(...listLenster)

猜你喜欢

转载自blog.csdn.net/qq_33988065/article/details/80150196
今日推荐