Vue.js源码分析:通过setter内嵌入函数来监听数据的变化

// 这个名为data的变量类同于我们在创建Vue实例的时候给传进去的data对象
const data = {
  msg: '这里的信息并不重要,因为我们要演示的是Vue.js是如何监听数据的变化的'
}
observe(data) // 函数会在下面定义
data.msg = '数据发生了变化'
function callback(){
  console.log('----------callback函数开始----------')
  console.log('我会在任何在上面定义好了的变量data下的值发生变化前运行')
  console.log('----------callback函数结束----------')
}

function observe(data){
  // 确保data存在以及data是合法的对象,以及
  // reactivate里面会调用observe,这样可以
  // 一层一层遍历所有data下的非原始数据类型的值
  if(!data || typeof data !== 'object') return
  // 遍历data变量里面所有可枚举的值
  Object.keys(data).forEach(function(key){
    reactivate(data, key, data[key]) // 后面会定义
  })
}

function reactivate(data, key, val){
  // 柯里函数,遍历掉data里面可能有的对象以及数组等,
  // 在这个示例里面我们没有搞玩得那么复杂
  observe(val)
  // 在JavaScript里面,所有的东西都是“对象”
  // 包括各种原始数据类型的值
  // 所有的“对象”都可以通过.defineProperty
  // 方法来设置新属性
  Object.defineProperty(data, key, {
    enumerable: true         // 可枚举
    , configurable: false    // 不能再被define
    , get: function() { return val }
    , set: function(newVal) { 
      callback()
      val = newVal
    }
  })
}

// 你可以试试运行如下代码
// data.msg = '我有setter,我是reactive的'
// data.newlyCreated = '我没有setter,我不是reactive的'