编辑代码

// const ins = new Vue({
//     data: {
//         a: 1
//     }
// })

// ins.$watch('a', () => {
//     console.log('修改了a')
// })

// 问题1:避免收集重复依赖
// 问题2:如何深度观测
// 问题3:如何处理数组及其他边界条件

// const data = {
//     a: 1,
//     b: 2
// }

// function walk (data) {
//     for (const key in data) {
//         const dep = []
//         let val = data[key]
//         Object.defineProperty(data, 'a', {
//             get: function () {
//                 console.log('获取a的值')
//                 // 获取属性值时,收集依赖
//                 dep.push(Target)
//                 return val
//             },
//             set: function (newVal) {
//                 console.log('设置a的值')
//                 if (newVal === val) return
//                 // 设置属性值时,执行依赖
//                 dep.forEach(fn => fn())
//             }
//         })

//     }
// }

// let Target = null
// function $watch (exp, fn) {
//     Target = fn
//     data[exp]
// }

// $watch('a', () => { console.log(111) })
// data.a = 2
// console.log('test', data.a)

// 如果嵌套对象,只能检测到第一层对象属性
const data = {
    a: {
        b: 1
    }
}

let Target = null

function walk (data) {
    for (let key in data) {
        const dep = []
        let val = data[key]
        if (typeof data[key] === 'object') {
            walk(val)
        }
        Object.defineProperty(data, key, {
            get() {
                dep.push(Target)
                console.log('val', val)
                console.log('dep', dep)
                return val
            },
            set(newVal) {
                if (newVal === val) return
                val = newVal
                dep.forEach(fn => fn())
            }
        })     
    }
}

walk(data)

//exp参考:'a'\'a.b'
function $watch (exp, fn) {
    Target = fn
    let obj = data
    if(/\./.test(exp)) {
        let keys = exp.split('.')
        for (let key of keys) {
            obj = obj[key]
        }
        return 
    }
    data[exp]
}

// 当watch的是个fn
function $watch (src, fn) {
    
}