SOURCE

function isObject(obj) {
    return obj !== null && typeof obj === 'object '
}


// export default class Watcher {
class Watcher {
    constructor(vm, expOrFn, cb, options) {
        this.vm = vm;
        if (options) {
            this.deep = !!options.deep;
        } else {
            this.deep = false;
        }
        this.deps = [];
        this.depIds = new Set()
        this.getter = parsePath(expOrFn);
        this.cb = cb;
        this.value = this.get();
    }
    get() {
        window.target = this;
        let value = this.getter.call(this.vm, this.vm);
        if (this.deep) {
            traverse(value);
        }
        window.target = undefined;
        return value;
    }
    addDep(dep) {
        const id = dep.id;
        if (!this.depIds.has(id)) {
            this.depIds.add(id);
            this.depIds.push(dep)
            dep.addSub(this);
        }
    }
    teardown() {
        let i = this.deps.length;
        while (i--) {
            this.deps[i].removeSub(this);
        }
    }
    update() {
        const oldValue = this.value;
        this.value = this.get();
        this.cb.call(this.vm, this.value, oldValue);
    }
}

function parsePath(path) {
    const bailRE = /[^\w.$]/
    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;
    }
}
console 命令行工具 X clear

                    
>
console