SOURCE

/*Object的变化侦测*/
		//对象的属性拦截
		function defineReactive(data,key,val){
            if(typeof val === 'object'){
                new Observer(val)
            }
			let dep = new Dep();
			Object.defineProperty(data,key,{
				enumerable:true,
				configurable:true,
				get:function(){
                    // console.log(1)
					dep.depend()
					return val;
				},
				set:function(newVal){
                    // console.log(2)
					if(val === newVal){
						return
					}
					val = newVal
                    dep.notify()
				}
			})
		}
        
        //依赖收集在哪里
		class Dep{
			constructor(){
				this.subs = [];
			}
			addSub(sub){
				this.subs.push(sub)
               
			}
			removeSub(sub){
				remove(this.subs,sub)
			}
			depend(){
				if(window.target){
					this.addSub(window.target)
				}
			}
			notify(){
                // console.log("3-1")
                // console.log(this.subs)
				const subs = this.subs.slice()
                // console.log(subs)
				for(let i =0;i <subs.length;i++){
					subs[i].update()
				}
			}
		}

		function remove(arr,item){
			if(arr.length){
				const index = arr.indexOf(item)
				if(index >-1){
					return arr.splice(index,1)
				}
			}
		}
        //依赖类
        class Watcher {
            constructor(vm,expOrFn,cb){
                // console.log("2-1")
                //vm是数据对象value
                //expOrFn是key
                //cb是回调函数
                this.vm = vm;
                this.getter = parsePath(expOrFn);
                //this.getter为返回函数A
                this.cb = cb;
        
                this.value = this.get();
            }

            get(){
                // console.log(this)
                window.target = this;
                let value = this.getter.call(this.vm,this.vm)
                window.target = undefined;
                return value
            
            }

            update(){
                // console.log("update")
                // console.log(this)
                const oldValue  = this.value;
                // console.log(oldValue)
                this.value = this.get();
                //  console.log(this.value)
                this.cb.call(this.vm,this.value,oldValue)
            }
        }

        const bailRE = /[^\w.$]/;
        function parsePath(path){
            if(bailRE.test(path)){
                return
            }
            const segments = path.split('.')
            //返回函数A 闭包函数
            return function(obj){
                //obj为数据对象value
                //segments为key
                // console.log("2-2")
                // console.log(obj)
                // console.log("-----")
                // console.log(segments)
                for(let i =0;i <segments.length;i++){
                    // console.log("2-3")
                    if(!obj)return
                    //  console.log("2-4")
                    obj = obj[segments[i]]
                }
                // console.log("2-5")
                // console.log(obj)
                return obj
            }
        }

        //侦测所有的key
        class Observer {
            constructor(value){
                this.value = value;
                if(!Array.isArray(value)){
                    this.walk(value)
                }
            }

            walk(obj){
                const keys = Object.keys(obj)
                for(let i = 0;i<keys.length;i++){
                    defineReactive(obj,keys[i],obj[keys[i]])
                }
            }
        }

        //vue类
        class Vue{
            constructor(options){
                new Observer(options)
                //给数据添加订阅者
                Object.keys(options).forEach(key=>{//按照options的属性循环实例化watcher
                    new Watcher(options,key,()=>{
                        console.log("这是回调方法")
                    });
                })
            }
        }

        let obj = {
            time:"12",
            hour:"21",
            secend:20,
            street:"灵魂",
        };

        new Vue(obj)
        obj.time = "17";
        /**
         * 数据初始化首先 实例化Obsever 并将对象数据作为参数传入 在observer实例中循环参数
         * 对象的值value,并对value调用defineReactive方法中实例化Dep 之后重新定义get和set。
         * get方法中收集依赖 set方法中派发依赖
         * 其次循环数据value 给value添加订阅者 并通过数据项get方法将value 加入dep实例中
         * 
         * **/
console 命令行工具 X clear

                    
>
console