用 ES6 代理替换原型时超出最大调用堆栈大小
Maximum call stack size exceeded when replacing prototype with ES6 Proxy
我有一个打字稿class装饰器
export function Profile(config: ProfilerConfig): ClassDecorator {
return function <TFunction extends Function> (target: TFunction) {
logToConsole = config.logToConsole || false;
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
};
}
我正在尝试用目标原型的代理替换原型,我得到了
ERROR RangeError: Maximum call stack size exceeded
但我没有看到任何明显的递归。当我使用
target.prototype = new Proxy(target.prototype , handler)
这不会发生。有什么想法吗?
target.prototype = new Proxy(target.prototype , handler)
这会将 target
的 prototype
设置为其自身的代理。
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
这会将 target.prototype
的 prototype
设置为 target.prototype
的代理。然后你有一个循环依赖:Object.getPrototypeOf(target.prototype) == proxy(target.prototype)
,所以当 JavaScript 试图遍历原型链时,它将陷入一个无限循环,一遍又一遍地调用代理处理程序。
我认为 Object.setPrototypeOf()
无论如何在这里没有任何意义。此函数旨在设置 实例 的原型。您似乎在尝试设置构造函数的原型,即 new constructor
创建实例时将从中继承的 constructor.prototype
对象。您需要像在第一个代码段中那样直接分配构造函数的 prototype
。
此处超过最大调用堆栈:
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
让我们看看这里发生了什么:您想向 target.prototype
添加代理。我不确定,是否可以,因为 MDN 对代理目标的描述:
A target object to wrap with Proxy. It can be any sort of object, including a native array, a function, or even another proxy.
但是对象的原型是 any sort of object
,所以假设您可以做到。
然后,您尝试添加代理原型作为目标原型的原型(抱歉)。像这样带圆圈的链接是超出堆栈的好方法。所以就在这里。
我认为一些简单 getter 的 JS 方式解决方法会对您有很大帮助:
Object.defineProperty(proto, 'foo', get: function() { ...} );
这不是特定于 target.prototype
,任何对象都会发生:
const o = {};
Object.setPrototypeOf(o, new Proxy(o, {}));
o.property;
您认为 property
来自哪里。它可以是 o
自己的 属性,也可以从其原型继承:代理说它不是自己的 属性,但它可以从其原型继承......这让我们陷入了递归 get
访问的困境。您可以尝试在您的代理处理程序上为此提供一个陷阱,您可以使用它来记录或调试递归。
请注意,Object.setPrototypeOf(o, o)
会抛出一个异常来禁止循环继承链,但代理会绕过它。
我有一个打字稿class装饰器
export function Profile(config: ProfilerConfig): ClassDecorator {
return function <TFunction extends Function> (target: TFunction) {
logToConsole = config.logToConsole || false;
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
};
}
我正在尝试用目标原型的代理替换原型,我得到了
ERROR RangeError: Maximum call stack size exceeded
但我没有看到任何明显的递归。当我使用
target.prototype = new Proxy(target.prototype , handler)
这不会发生。有什么想法吗?
target.prototype = new Proxy(target.prototype , handler)
这会将 target
的 prototype
设置为其自身的代理。
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
这会将 target.prototype
的 prototype
设置为 target.prototype
的代理。然后你有一个循环依赖:Object.getPrototypeOf(target.prototype) == proxy(target.prototype)
,所以当 JavaScript 试图遍历原型链时,它将陷入一个无限循环,一遍又一遍地调用代理处理程序。
我认为 Object.setPrototypeOf()
无论如何在这里没有任何意义。此函数旨在设置 实例 的原型。您似乎在尝试设置构造函数的原型,即 new constructor
创建实例时将从中继承的 constructor.prototype
对象。您需要像在第一个代码段中那样直接分配构造函数的 prototype
。
此处超过最大调用堆栈:
Object.setPrototypeOf(
target.prototype,
new Proxy(target.prototype , handler)
);
让我们看看这里发生了什么:您想向 target.prototype
添加代理。我不确定,是否可以,因为 MDN 对代理目标的描述:
A target object to wrap with Proxy. It can be any sort of object, including a native array, a function, or even another proxy.
但是对象的原型是 any sort of object
,所以假设您可以做到。
然后,您尝试添加代理原型作为目标原型的原型(抱歉)。像这样带圆圈的链接是超出堆栈的好方法。所以就在这里。
我认为一些简单 getter 的 JS 方式解决方法会对您有很大帮助:
Object.defineProperty(proto, 'foo', get: function() { ...} );
这不是特定于 target.prototype
,任何对象都会发生:
const o = {};
Object.setPrototypeOf(o, new Proxy(o, {}));
o.property;
您认为 property
来自哪里。它可以是 o
自己的 属性,也可以从其原型继承:代理说它不是自己的 属性,但它可以从其原型继承......这让我们陷入了递归 get
访问的困境。您可以尝试在您的代理处理程序上为此提供一个陷阱,您可以使用它来记录或调试递归。
请注意,Object.setPrototypeOf(o, o)
会抛出一个异常来禁止循环继承链,但代理会绕过它。