JavaScript可通过原型链、构造函数prototype、Proxy三种方式实现属性动态映射:Object.create构建代理原型转发访问;prototype上定义getter统一管理别名;Proxy结合原型链实现灵活条件映射,避免污染全局。

通过原型链实现属性的动态映射,本质是利用 JavaScript 属性查找机制——当访问对象属性时,若自身不存在,引擎会沿 [[Prototype]] 链向上查找。我们可主动构造或修改这条链,让“读取某个键”实际返回另一个键的值,无需复制或重命名原始数据。
用 Object.create 搭建映射原型
这是最干净、无副作用的方式:创建一个空对象作为代理原型,将其 __proto__ 指向源对象,并在代理上定义 getter,把请求转发到源对象的指定字段。
- 不修改源对象结构,也不污染实例自身属性
- 所有通过该原型访问的实例共享同一套映射逻辑
- 适合统一处理一批对象的字段别名(如 API 返回的
user_name映射为name)
示例:
const userData = { user_name: 'Alice', user_id: 123 };<br>const aliasProto = Object.create(userData);<br>Object.defineProperty(aliasProto, 'name', {<br> get() { return this.user_name; },<br> enumerable: true<br>});<br>Object.defineProperty(aliasProto, 'id', {<br> get() { return this.user_id; },<br> enumerable: true<br>});<br><br>const user = Object.create(aliasProto);<br>console.log(user.name); // 'Alice'<br>console.log(user.id); // 123
在 prototype 上批量定义 getter
适用于构造函数场景。把字段映射逻辑写在构造函数的 prototype 上,所有实例自动获得一致的别名访问能力。
- 映射规则集中管理,便于维护和复用
- 支持运行时动态更新 getter,所有实例即时生效
- 注意避免与实例自有属性冲突(getter 仅在自身无该属性时触发)
示例:
function User(data) {<br> Object.assign(this, data);<br>}<br><br>User.prototype = {<br> get name() { return this.user_name; },<br> set name(val) { this.user_name = val; },<br> get id() { return this.user_id; }<br>};<br><br>const u = new User({ user_name: 'Bob', user_id: 456 });<br>console.log(u.name); // 'Bob'<br>u.name = 'Charlie';<br>console.log(u.user_name); // 'Charlie'
拦截访问:用 Proxy + 原型链配合
Proxy 本身不依赖原型链,但可与原型链协同:让 Proxy 的 get 拦截器先查自身,再 fallback 到原型链查找,同时加入字段映射逻辑。
- 灵活性最高,能实现条件映射、嵌套路径解析等复杂规则
- 不影响原有原型结构,兼容已有继承关系
- 性能略低于纯原型方案,适合对映射逻辑有动态判断需求的场景
示例(简单映射):
const map = { userName: 'user_name', userId: 'user_id' };<br>const data = { user_name: 'David', user_id: 789 };<br><br>const proxied = new Proxy(data, {<br> get(obj, key) {<br> const mappedKey = map[key] || key;<br> return obj[mappedKey] !== undefined<br> ? obj[mappedKey]<br> : obj[mappedKey] === undefined && obj.__proto__[mappedKey];<br> }<br>});<br><br>console.log(proxied.userName); // 'David'
慎用:直接修改 Object.prototype
理论上可在 Object.prototype 上添加通用 getter 实现全局映射,但强烈不推荐。
- 污染全局环境,影响所有对象,极易引发不可预知的冲突
- 破坏代码可预测性,调试困难
- 现代规范(如严格模式)可能限制此类操作
替代思路:封装一个工具函数(如 mapKeys(obj, rules)),按需返回带映射行为的新对象或 Proxy,保持作用域隔离。

















