构造函数可通过显式返回 Proxy 对象实现属性拦截,前提是返回非 null 对象;返回原始值则忽略,仍返回默认实例。需用 Object.setPrototypeOf 修复原型链以支持 instanceof 和方法调用。

构造函数本身不能直接返回代理对象来实现属性拦截,因为 new 调用会强制返回一个以该构造函数为原型的新对象(除非显式返回一个非 null 的对象)。但你可以通过“在构造函数中返回一个 Proxy 实例”来绕过默认行为,从而实现对实例属性的拦截。
构造函数返回 Proxy 的前提条件
根据 ECMAScript 规范,当构造函数执行 return 语句时:
- 如果返回的是一个对象(包括
Proxy、数组、函数等),new表达式就返回这个对象,忽略默认创建的实例; - 如果返回的是原始值(
string、number、null、undefined等),则忽略返回值,仍返回默认实例。
所以关键点是:构造函数必须显式 return 一个 Proxy 对象,且该 Proxy 的 target 通常是你想代理的普通对象(可以是空对象或预设数据)。
DMap GL地图JSAPI(dmapgl)开发指南。用于编写、审查、调试 DMap 地图 API 代码,涵盖地图初始化、覆盖物渲染、图层管理、事件处理、控件交互等任务。当用户提及 dmap、dmapgl、jsapi‑gl 或相关地图开发需求时自动触发。
基础示例:返回代理对象并拦截 get/set
下面是一个能正常工作的例子:
function MyObj(name) {
// 创建原始数据载体(可带初始值)
const data = { name, age: 0 };
// 创建代理,拦截读写
const proxy = new Proxy(data, {
get(target, key) {
console.log(`[get] ${key}`);
return target[key];
},
set(target, key, value) {
console.log(`[set] ${key} = ${value}`);
target[key] = value;
return true;
}
});
// ✅ 显式返回代理对象,覆盖 new 默认行为
return proxy;
}
const obj = new MyObj("Alice");
obj.age = 25; // [set] age = 25
console.log(obj.name); // [get] name → "Alice"
保持原型链(可选但推荐)
直接返回 Proxy 会导致新实例丢失构造函数的 prototype,比如 obj instanceof MyObj 会是 false。若需保留原型关系,可以用 Object.setPrototypeOf 手动设置:
function MyObj(name) {
const data = { name, age: 0 };
const proxy = new Proxy(data, {
get(target, key, receiver) {
// 使用 receiver 保证 this 正确(如调用方法时)
return Reflect.get(target, key, receiver);
},
set(target, key, value, receiver) {
return Reflect.set(target, key, value, receiver);
}
});
// 把 MyObj.prototype 挂到 proxy 上,让 instanceof 生效
Object.setPrototypeOf(proxy, MyObj.prototype);
return proxy;
}
MyObj.prototype.sayHi = function() {
return `Hi, I'm ${this.name}`;
};
const obj = new MyObj("Bob");
console.log(obj instanceof MyObj); // true
console.log(obj.sayHi()); // "Hi, I'm Bob"
注意事项与常见陷阱
-
不要在 Proxy 中直接操作
this:代理内部的get/set回调里没有传统意义上的this,应始终操作target或通过receiver; -
避免循环代理:不要让
target是另一个Proxy,否则可能触发无限递归; -
谨慎处理函数属性:若
target上有方法,确保get返回的函数执行时this指向代理本身(Reflect.get+receiver可帮上忙); -
new.target 在代理中不可靠:代理对象内部无法自然感知是否被
new调用,如有需要,建议改用工厂函数(如createMyObj())替代构造函数。

















