Object.defineProperty

vue如何实现数据的双向绑定

其中Object.defineProperty可以给对象添加setter和getter
$watch可以知道检测的是哪一个属性从而为这个属性值添加

function walk (data) {
  for (let key in data) {
    const dep = []
    let val = data[key]
    // 如果 val 是对象,递归调用 walk 函数将其转为访问器属性
    const nativeString = Object.prototype.toString.call(val)
    if (nativeString === '[object Object]') {
      walk(val)
    }
    Object.defineProperty(data, key, {
      set (newVal) {
        if (newVal === val) return
        val = newVal
        dep.forEach(fn => fn())
      },
      get () {
        dep.push(Target)
        return val
      }
    })
  }
}
function $watch (exp, fn) {
  Target = fn
  let pathArr,
      obj = data
  // 如果 exp 是函数,直接执行该函数
  if (typeof exp === 'function') {
    exp()
    return
  }
  if (/\./.test(exp)) {
    pathArr = exp.split('.')
    pathArr.forEach(p => {
      obj = obj[p]
    })
    return
  }
  data[exp]
}
walk(data)

proxy的优势

defineProperty缺点在于无法响应数组索引,对于深层对象需要递归观测
而proxy可以劫持整个对象并返回一个新对象,并且有13种劫持方法,之前是由于这个是es6的方法,兼容性不好

你可能感兴趣的:(Object.defineProperty)