响应式系统实现深度解析

核心思想:聚焦能力

  • 问题拆解:将复杂问题分解为独立子目标,逐个击破
  • 精力分配:集中有限资源攻克关键点,避免分散
  • 实践验证:在代码实现中反复验证认知,逐步完善设计

核心能力实现

1. 监听(Tracking)

关键实现

const targetMap = new WeakMap()
 
function reactive(target) {
  if (!isObject(target)) return target
  if (targetMap.has(target)) return targetMap.get(target)
  
  const proxy = new Proxy(target, handlers)
  targetMap.set(target, proxy)
  return proxy
}

关键技术点

  • WeakMap缓存:解决重复代理问题,防止内存泄漏
  • 边界处理:非对象直接返回
  • 模块分离:代理处理逻辑抽离到handlers模块

2. 读取(Read)

处理类型

操作类型对应场景内部方法
trackOpTypes.GET属性访问 obj.a[[Get]]
trackOpTypes.HASin 操作符[[Has]]
trackOpTypes.ITERATEfor...in 循环[[OwnKeys]]

代码实现

// handlers.js
const handlers = {
  get(target, key, receiver) {
    track(target, trackOpTypes.GET, key)
    const value = Reflect.get(target, key, receiver)
    return isObject(value) ? reactive(value) : value
  },
  has(target, key) {
    track(target, trackOpTypes.HAS, key)
    return Reflect.has(target, key)
  },
  ownKeys(target) {
    track(target, trackOpTypes.ITERATE)
    return Reflect.ownKeys(target)
  }
}

关键技术点

  • Reflect的使用:正确传递receiver保证this指向
  • 深度代理:递归处理对象属性
  • 操作类型区分:精确追踪不同读取场景

3. 修改(Write)

处理类型

操作类型触发场景内部方法
triggerOpTypes.SET属性修改 obj.a = 1[[Set]]
triggerOpTypes.ADD新增属性 obj.b = 2[[Set]]
triggerOpTypes.DELETE删除属性 delete obj.c[[Delete]]

代码实现

// handlers.js
const handlers = {
  set(target, key, value, receiver) {
    const oldValue = target[key]
    const hadKey = Object.prototype.hasOwnProperty.call(target, key)
    const result = Reflect.set(target, key, value, receiver)
    
    if (!result) return result
    
    const type = hadKey 
      ? triggerOpTypes.SET 
      : triggerOpTypes.ADD
    
    if (!hadKey || hasChanged(value, oldValue)) {
      trigger(target, type, key)
    }
    return result
  },
  deleteProperty(target, key) {
    const hadKey = Object.prototype.hasOwnProperty.call(target, key)
    const result = Reflect.deleteProperty(target, key)
    
    if (hadKey && result) {
      trigger(target, triggerOpTypes.DELETE, key)
    }
    return result
  }
}
 
// utils.js
export function hasChanged(value, oldValue) {
  return !Object.is(value, oldValue)
}

关键技术点

  • 变化检测:使用Object.is处理NaN和±0的特殊情况
  • 类型判断:区分修改和新增操作
  • 有效性验证:处理只读属性等边界情况

架构优化

模块化设计

src/
├── reactive.js      # 主入口
├── handlers.js      # Proxy处理函数
├── operations.js    # 操作类型常量
└── utils.js         # 工具函数

关键工具函数

// utils.js
export function isObject(value) {
  return value !== null && typeof value === 'object'
}
 
export function hasChanged(value, oldValue) {
  return !Object.is(value, oldValue)
}

深度思考

  1. WeakMap vs Map

    • 弱引用特性防止内存泄漏
    • 适合建立对象与代理的映射关系
  2. Reflect的必要性

    • 正确传递receiver保持上下文
    • 对齐Proxy handler方法参数
  3. 操作类型关联

    • for...in → 响应属性增删
    • in操作符 → 响应属性存在性变化
    • 属性读取 → 响应值变化

待处理问题(下节课内容)

  1. 数组方法的特殊处理(push/pop等)
  2. 嵌套数组的响应式处理
  3. 性能优化:避免重复触发依赖
  4. 循环引用处理

通过聚焦每个关键点的实现,逐步构建出完整的响应式系统。下节课将深入处理数组相关特性和性能优化。