← 返回目录

第 7 卷

第 7 / 8 卷日期:

75this.off(eventName, onceCallback);

76};

77// 订阅包装后的回调 78this.on(eventName, onceCallback);

79} 80}

81 82// 测试示例

83const eventBus = new EventBus();

84 85// 1. 普通订阅与发布

86function handleTest(arg1, arg2) { 87console.log('普通事件触发:', arg1, arg2);

88}

十二、手写函数柯里化(curry)的代码实现

核心原理

  1. 柯里化是将接收多个参数的函数,转化为接收单一参数(或部分参数)的函数序列的过程,最终返

回接收剩余参数并执行原函数的函数

  1. 核心逻辑:保存已接收的参数,判断已接收参数数量是否达到原函数的参数长度(形参长度),若

达到则执行原函数,否则返回一个新函数继续接收参数

  1. 支持特性:
  • 自动判断参数是否足够,足够则执行
  • 支持分步传递参数,也支持一次性传递所有参数
  • 兼容原函数的this指向
  1. 依赖原函数的 length 属性获取形参数量,若原函数是剩余参数(...rest)形式,需手动指定参数

长度

实现代码

Code block

1/** 2* 函数柯里化

3* @param {Function} fn - 待柯里化的原函数 4* @param {number} [arity=fn.length] - 原函数的参数长度(若原函数用rest参数,需手动

指定)

5* @returns {Function} 柯里化后的函数

11} 12

13// 递归生成柯里化函数,接收已传递的参数(闭包保存)

14const curried = function(...args) {

15const _this = this; //保存当前this指向(用于原函数执行时绑定)
16//情况1:已传递的参数数量>=原函数参数长度,执行原函数
17if (args.length >= arity) {
18return fn.apply(_this, args);
19}
20//情况2:参数不足,返回新函数继续接收参数
21return function(...nextArgs) {
22//合并已接收的参数和新传递的参数,递归调用curried
23return curried.apply(_this, [...args, ...nextArgs]);
24};
25};

26 27return curried;

28} 29

30// 测试示例 31// 1. 普通函数柯里化

32function add(a, b, c) { 33return a + b + c;

34} 35const curriedAdd = curry(add);

36 37// 分步传递参数

38console.log(curriedAdd(1)(2)(3)); // 6
39console.log(curriedAdd(1, 2)(3)); // 6
40console.log(curriedAdd(1)(2, 3)); // 6

41 42// 一次性传递所有参数

43console.log(curriedAdd(1, 2, 3)); // 6 44

45// 2. 绑定this的柯里化函数 46const obj = {

47name: '柯里化', 48sayHello: function(greet, msg) {

49return `${greet},${this.name}:${msg}`;

51};

52const curriedSayHello = curry(obj.sayHello);

56// 3.处理rest参数函数(需手动指定参数长度)
57function sum(...args) {
58return args.reduce((total, curr) => total + curr, 0);
59}
60//手动指定需要接收3个参数
61const curriedSum = curry(sum, 3);
62console.log(curriedSum(1)(2)(3)); // 6
63console.log(curriedSum(1, 2)(3)); // 6

64

十三、手写Vue3响应式原理的代码实现(简易版)

核心原理(Vue3 vs Vue2)

  1. Vue3 响应式核心从 Vue2 的 Object.defineProperty 改为Proxy,解决了 Vue2 的缺陷:
  • 支持数组索引/长度变化的响应式
  • 支持新增/删除对象属性的响应式
  • 无需递归劫持初始对象的所有属性(Proxy 是懒代理,访问属性时才触发劫持)
  1. 核心模块:
  • Proxy:代理目标对象,拦截属性的读取(get)和设置(set)操作
  • Reflect:配合 Proxy 操作目标对象,确保操作的正确性和规范性
  • effect:副作用函数(如组件渲染函数),依赖收集时记录该函数,数据变化时重新执行
  • track:依赖收集,在 Proxy 的 get 拦截中调用,记录“目标对象-属性-副作用函数”的映射关系
  • trigger:触发更新,在 Proxy 的 set 拦截中调用,找到对应属性的所有副作用函数并执行
  1. 依赖存储:用 WeakMap(目标对象 -> Map(属性名 -> Set(副作用函数)))的结构,避免内存

泄漏

实现代码

Code block

1// 1. 存储依赖的结构:WeakMap<target, Map<key, Set<effect>>> 2const targetMap = new WeakMap();

3

4// 2.当前活跃的副作用函数(依赖收集时需要记录)
5let activeEffect = null;
7/**
全站分卷索引 · 8 卷
  1. 1第 1 卷
  2. 2第 2 卷
  3. 3第 3 卷
  4. 4第 4 卷
  5. 5第 5 卷
  6. 6第 6 卷
  7. 7第 7 卷
  8. 8第 8 卷