# JavaScript 数据代理实现文档 ## 一、基本概念 数据代理是指通过一个对象(代理对象)间接访问和操作另一个对象(目标对象)的属性。本示例展示了如何使用 `Object.defineProperty` 实现简单的数据代理。 ## 二、代码实现解析 ```javascript let obj1 = { x: 100 }; // 目标对象(被代理对象) let obj2 = { y: 200 }; // 代理对象 // 在obj2上定义x属性的代理 Object.defineProperty(obj2, "x", { get() { return obj1.x; // 读取时返回obj1的x属性 }, set(value) { obj1.x = value; // 设置时修改obj1的x属性 } }); ``` ## 三、核心机制说明 1. **代理原理**: - 通过 `Object.defineProperty` 在代理对象(obj2)上定义新属性 - 使用 getter/setter 方法实现对目标对象(obj1)属性的间接访问 2. **访问流程**: - 读取 `obj2.x` → 触发 getter → 返回 `obj1.x` 的值 - 设置 `obj2.x` → 触发 setter → 将值赋给 `obj1.x` 3. **特性**: - 透明的属性访问(使用者无需知道代理存在) - 可以在访问前后执行额外逻辑(如验证、日志等) ## 四、应用场景 | 场景 | 说明 | 示例 | | -------- | -------------------- | ------------------------------ | | 属性转发 | 跨对象访问属性 | 本示例实现 | | 数据验证 | 设置属性前检查有效性 | setter中添加验证逻辑 | | 访问控制 | 限制某些属性的访问 | getter中添加权限检查 | | 日志记录 | 跟踪属性访问 | getter/setter中添加console.log | ## 五、扩展实现 ### 1. 多属性代理 ```javascript function proxyProperties(target, source, props) { props.forEach(prop => { Object.defineProperty(target, prop, { get() { return source[prop]; }, set(value) { source[prop] = value; } }); }); } // 使用示例 proxyProperties(obj2, obj1, ['x', 'a', 'b']); ``` ### 2. Vue2 风格的数据代理 ```javascript function observe(obj) { const handler = { get(target, prop) { console.log(`读取 ${prop}`); return target[prop]; }, set(target, prop, value) { console.log(`设置 ${prop} 为 ${value}`); target[prop] = value; return true; } }; return new Proxy(obj, handler); } const observed = observe(obj1); ``` ## 六、注意事项 1. **性能考虑**: - 每个代理属性都会增加访问开销 - 避免在性能关键路径上过度使用 2. **引用关系**: - 代理对象和目标对象保持独立 - 修改代理属性会影响原始对象 3. **枚举特性**: - 默认情况下代理属性不可枚举 - 需要显式设置 `enumerable: true` 4. **兼容性**: - `Object.defineProperty` 是 ES5 特性 - 现代开发可考虑使用 ES6 Proxy