手写
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