Skip to content

手写

reduce

js
// 语法规则
// [].reduce((res, cut, idx, this) => { return res; }, val);

// 模仿实现
function reduce(arr, callback, initValue) {
    let res = initValue;
    for (let i = 0; i < arr.length; i++) {
        let cut = arr[i];
        res = callback(res, cut, i, arr);
    }
    return res;
}

// 测试代码
const nums = [1, 2, 3];
const res = reduce(nums, (sum, value) => (sum += value), 0);
const res2 = nums.reduce((sum, value) => (sum += value), 0);
console.log(res === res2); // true
// 语法规则
// [].reduce((res, cut, idx, this) => { return res; }, val);

// 模仿实现
function reduce(arr, callback, initValue) {
    let res = initValue;
    for (let i = 0; i < arr.length; i++) {
        let cut = arr[i];
        res = callback(res, cut, i, arr);
    }
    return res;
}

// 测试代码
const nums = [1, 2, 3];
const res = reduce(nums, (sum, value) => (sum += value), 0);
const res2 = nums.reduce((sum, value) => (sum += value), 0);
console.log(res === res2); // true

curry

js
// 版本一
function curry(fn) {
    let allArg = [];
    return function curryFn(...args) {
        allArg = allArg.concat(args);
        if (allArg.length < fn.length) return curryFn;
        return fn(...allArg);
    };
}

// 版本二
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.call(this, ...args);
        }
        return (...args2) => curried.apply(this, args.concat(args2));
    };
}

// 示例函数
function add(a, b, c) {
    return a + b + c;
}

// 使用柯里化转换示例函数
const curriedAdd = curry(add);
console.log(curriedAdd(1, 2, 3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2)(3)); // 6

let curriedAdd2 = curry(add);
curriedAdd2 = curriedAdd2(1);
curriedAdd2 = curriedAdd2(2);
console.log(curriedAdd2(3)); // 6
// 版本一
function curry(fn) {
    let allArg = [];
    return function curryFn(...args) {
        allArg = allArg.concat(args);
        if (allArg.length < fn.length) return curryFn;
        return fn(...allArg);
    };
}

// 版本二
function curry(fn) {
    return function curried(...args) {
        if (args.length >= fn.length) {
            return fn.call(this, ...args);
        }
        return (...args2) => curried.apply(this, args.concat(args2));
    };
}

// 示例函数
function add(a, b, c) {
    return a + b + c;
}

// 使用柯里化转换示例函数
const curriedAdd = curry(add);
console.log(curriedAdd(1, 2, 3)); // 6
console.log(curriedAdd(1, 2)(3)); // 6
console.log(curriedAdd(1)(2)(3)); // 6

let curriedAdd2 = curry(add);
curriedAdd2 = curriedAdd2(1);
curriedAdd2 = curriedAdd2(2);
console.log(curriedAdd2(3)); // 6

reactivity

js
// 参照 @vue/reactivity, 涉及 ref、reactive、effect 三个模块实现

class Dep {
    constructor() {
        this.effects = new Map(); // [{ [Object]: new Set() }]
    }
    depend(obj, effect) {
        let list = this.effects.get(obj) || new Set();
        list.add(effect);
        this.effects.set(obj, list);
    }
    notice(obj) {
        const list = this.effects.get(obj);
        list && list.forEach((effect) => effect());
    }
}

const dep = new Dep();

const effectStack = [];

const effect = function (fn) {
    const effectFn = function () {
        if (!effectStack.includes()) {
            effectStack.push(effectFn);
        }
        let res = fn();
        effectStack.pop();
        return res;
    };
    effectFn();
    return effectFn;
};

const ref = function (value) {
    const obj = { value };
    const handler = {
        get() {
            const value = Reflect.get(...arguments);
            const effect = effectStack[effectStack.length - 1];
            effect && dep.depend(obj, effect);
            return value;
        },
        set() {
            const res = Reflect.set(...arguments);
            dep.notice(obj);
            return res;
        },
    };
    return new Proxy(obj, handler);
};

const reactive = function (obj) {
    const handler = {
        get() {
            const val = Reflect.get(...arguments);
            const effect = effectStack[effectStack.length - 1];
            effect && dep.depend(obj, effect);
            // 嵌套对象递归代理
            return typeof val === "object" ? new Proxy(val, handler) : val;
        },
        set() {
            const res = Reflect.set(...arguments);
            dep.notice(obj);
            return res;
        },
    };
    return new Proxy(obj, handler);
};

// =============================
// ========= 测试用例 ===========
// =============================

let a = ref(0);
let obj = reactive({
    b: { b1: 1, b2: 2 },
});
let c, d;
effect(() => {
    c = a.value + 1;
    console.log(c);
});
effect(() => {
    d = obj.b.b2 + 1;
    console.log(d);
});
a.value++;
obj.b.b2++;
// 日志: 1
// 日志: 3
// 日志: 2
// 日志: 4
// 参照 @vue/reactivity, 涉及 ref、reactive、effect 三个模块实现

class Dep {
    constructor() {
        this.effects = new Map(); // [{ [Object]: new Set() }]
    }
    depend(obj, effect) {
        let list = this.effects.get(obj) || new Set();
        list.add(effect);
        this.effects.set(obj, list);
    }
    notice(obj) {
        const list = this.effects.get(obj);
        list && list.forEach((effect) => effect());
    }
}

const dep = new Dep();

const effectStack = [];

const effect = function (fn) {
    const effectFn = function () {
        if (!effectStack.includes()) {
            effectStack.push(effectFn);
        }
        let res = fn();
        effectStack.pop();
        return res;
    };
    effectFn();
    return effectFn;
};

const ref = function (value) {
    const obj = { value };
    const handler = {
        get() {
            const value = Reflect.get(...arguments);
            const effect = effectStack[effectStack.length - 1];
            effect && dep.depend(obj, effect);
            return value;
        },
        set() {
            const res = Reflect.set(...arguments);
            dep.notice(obj);
            return res;
        },
    };
    return new Proxy(obj, handler);
};

const reactive = function (obj) {
    const handler = {
        get() {
            const val = Reflect.get(...arguments);
            const effect = effectStack[effectStack.length - 1];
            effect && dep.depend(obj, effect);
            // 嵌套对象递归代理
            return typeof val === "object" ? new Proxy(val, handler) : val;
        },
        set() {
            const res = Reflect.set(...arguments);
            dep.notice(obj);
            return res;
        },
    };
    return new Proxy(obj, handler);
};

// =============================
// ========= 测试用例 ===========
// =============================

let a = ref(0);
let obj = reactive({
    b: { b1: 1, b2: 2 },
});
let c, d;
effect(() => {
    c = a.value + 1;
    console.log(c);
});
effect(() => {
    d = obj.b.b2 + 1;
    console.log(d);
});
a.value++;
obj.b.b2++;
// 日志: 1
// 日志: 3
// 日志: 2
// 日志: 4

༼ つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿◕ _◕ ༽つ/̵͇̿̿/’̿’̿ ̿ ̿̿ ̿̿ ̿̿