class Dep { constructor() { this.subs = new Map(); } addSub(key, sub) { const hasSub = this.subs.get(key); if (hasSub) { hasSub.add(sub); } else { this.subs.set(key, new Set([sub])); } } notify(key) { if (this.subs.get(key)) { this.subs.get(key).forEach(sub => { sub.update(); }); } } } class Watcher { constructor(obj, key, cb) { this.obj = obj; this.key = key; this.cb = cb; // åè° this.value = this.get(); // è·åèæ°æ® } get() { Dep.target = this; let value = this.obj[this.key]; Dep.target = null; return value; } // å°è®¢é è æ¾å ¥å¾ æ´æ°éåçå¾ æ¹éæ´æ° update() { let newVal = this.obj[this.key]; if (this.value !== newVal) { this.cb(newVal); } } } function Observer(obj) { Object.keys(obj).forEach(key => { // åæ·±åº¦çå¬ if (typeof obj[key] === 'object') { obj[key] = Observer(obj[key]); } }); let dep = new Dep(); let handler = { get: function (target, key, receiver) { Dep.target && dep.addSub(key, Dep.target); return Reflect.get(target, key, receiver); }, set: function (target, key, value, receiver) { let result = Reflect.set(target, key, value, receiver); dep.notify(key); return result; } }; return new Proxy(obj, handler) } let data = { name: '渣渣è¾' }; function print1(data) { console.log('æç³»', data); } function print2(data) { console.log('æä»å¹´', data); } data = Observer(data); new Watcher(data, 'name', print1); data.name = 'æ¨è¿'; // æç³» æ¨è¿ new Watcher(data, 'age', print2); data.age = '24'; // æä»å¹´ 24 console.log(data);