SOURCE

const bucket = new WeakMap();

let activeEffect = null;
const effectStack = [];

//封装收集副作用函数
function track(target,key){
    if(!activeEffect){
        return target[key]
    }
    //取出与target绑定的map
    let depsMap = bucket.get(target);
    if(!depsMap){
        bucket.set(target, (depsMap = new Map()));
    }
    //取出与key对应的副作用函数
    let depsEffets = depsMap.get(key);
    if(!depsEffets){
        depsMap.set(key, (depsEffets = new Set()));
    }
    depsEffets.add(activeEffect);
    activeEffect.deps.push(depsEffets)
}
//封装触发副作用函数
function trigger(target, key){
    const depsMap = bucket.get(target);
    if(!depsMap){
        return
    }
    const depsEffets = depsMap.get(key);
    const effectsToRun = new Set();
    depsEffets.forEach(effectfn=>{
        if(effectfn!==activeEffect){
            effectsToRun.add(effectfn)
        }
    })
    effectsToRun&&effectsToRun.forEach(fn=>{
        if(fn.option.scheduler){
            fn.option.scheduler(fn)
        }else{
            fn()
        }
    });
}

function reactive(data){
    const obj = new Proxy(data, {
        get(target, key){
            track(target, key);
            return target[key];
        },
        set(target, key, value){
            target[key] = value;
            trigger(target,key,value);
            return true;
        }
    })
    return obj;
}

const cleanup = (effectFn) => {
    for(let i=0;i<effectFn.deps.length; i++){
        const deps = effectFn.deps[i];
        deps.delete(effectFn)
    }
    effectFn.deps.length = 0;
}

const effect = (fn, option={})=>{
    const effectFn = () => {
        cleanup(effectFn)
        activeEffect = effectFn;
        effectStack.push(activeEffect);
        fn();
        effectStack.pop();
        activeEffect = effectStack[effectStack.length-1];
    }
    effectFn.option = option;
    effectFn.deps = []
    effectFn();
};

const jobQueue = new Set();
let isFlushing = false;
function flushJob(){
    if(isFlushing) return;
    isFlushing = true;
    const p = Promise.resolve();
    p.then(()=>{
        jobQueue.forEach(job=>job());
    }).finally(()=>{
        isFlushing = false;
    })
}



const obj1 = reactive({name: "李翔", ok:true, age: 1})

effect(function effectfn(){
    console.log(obj1.age)
    },{
    scheduler(effectfn){
        jobQueue.add(effectfn);
        flushJob();
    }
})

obj1.age++;
obj1.age++;
obj1.age++;
obj1.age++;
obj1.age++;
obj1.age++;


console 命令行工具 X clear

                    
>
console