SOURCE

class Observer {
    constructor(value) {
        this.value = value
        def(value, '__ob__',this)
        if (Array.isArray(value)) {

        }else {
           
            this.walk(value)
        }
    }

    walk (obj) {
        const keys = Object.keys(obj)
        keys.forEach(key => {
            defineReactive(obj, key)
        })
    }
}

class Dep {
    constructor () {
        this.subs = []
    }

    addSub (sub) {
        this.subs.push(sub)
    }
    removeSub (sub) {
        this.subs = this.subs.filter(item !== sub)
    }
    depend () {
        if (window.target) {
            this.addSub(window.target)
        }
    }
    notify () {
        const subs = this.subs.slice()
        subs.forEach(sub => sub.update())
    }
}

class Watcher {
  constructor (vm,expOrFn,cb) {
    this.vm = vm;
    this.cb = cb;
    this.getter = parsePath(expOrFn)
    this.value = this.get()
  }
  get () {
    window.target = this;
    const vm = this.vm
    let value = this.getter.call(vm, vm)
    window.target = undefined;
    return value
  }
  update () {
    const oldValue = this.value
    this.value = this.get()
    console.log('update')
    this.cb.call(this.vm, this.value, oldValue)
  }
}
function def(obj, key, val, enumerable) {
    Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
    })
}
function defineReactive(obj, key, val, customSetter, shallow) {
    if (arguments.length === 2) {
        val = obj[key]
    }
    if (typeof val === 'object') {
        new Observer(val)
    }
    const dep = new Dep()
    Object.defineProperty(obj, key, {
        enumerable: true,
        configurable: true,
        get(){
            console.log(`${key}属性被读取了`);
            dep.depend()
            return val;
        },
        set(newVal){
            if(val === newVal){
                return
            }
            console.log(`${key}属性被修改了`);
            val = newVal;
            dep.notify()
        }
    })
}
const bailRE = /[^\w.$]/
 function parsePath (path) {
  if (bailRE.test(path)) {
    return
  }
  const segments = path.split('.')
  return function (obj) {
    for (let i = 0; i < segments.length; i++) {
      if (!obj) return
      obj = obj[segments[i]]
    }
    return obj
  }
}
let car = new Observer({
  'brand':'BMW',
  'price':3000
}).value
let watch = new Watcher ({
    car: car,
   
} ,'',[]).vm.car
watch.brand = 1
console 命令行工具 X clear

                    
>
console