我在拦截对库的构造函数调用时遇到了一些麻烦(这样我可以稍后重播它们),同时仍然维护原型链。更具体地说,我正在使用一个库(ThreeJS,但可以是任何库),以及一些使用该库的代码。我想做的是编写一段修改库对象的代码,这样我就可以在每次调用构造函数时运行一段代码。
示例:当创建一个新场景时,我想将“new Scene created”打印到控制台。
var scene = new THREE.Scene();
当构造函数接受参数时,我也想记录这些参数。
我对此不确定,但是...你可以尝试类似...
// Backup the original constructor somewhere
THREE._Scene = THREE.Scene;
// Override with your own, then call the original
THREE.Scene = function() {
// Do whatever you want to do here..
THREE._Scene.apply(this, arguments);
}
// Extend the original class
THREE.Scene.prototype = Object.create(THREE._Scene.prototype);
使用代理:
THREE.Scene = new Proxy(THREE.Scene, {
construct(target, args) {
console.log(`creating a ${target.name} with ${args}`);
return new target(...args);
}
});
从@bvaughn 代码开始,这对我有用:
THREE._Scene = THREE.Scene;
THREE.Scene = function() {
const Scene = Function.prototype.bind.apply(THREE._Scene, arguments);
const scene = new Scene()
console.log("Intercepted scene:", scene)
return scene;
}
THREE.Scene.prototype = Object.create(THREE._Scene.prototype);
// Test
const scene = new THREE.Scene()
// Prints "Intercepted scene:", ....
Yoz 的“使用代理”答案对于现代来说是正确的(谢谢!),但是它对于类实现不太适用,因为你无法将类的名称重新定义为变量。
这是我使用类的示例。这里它用于实现一种典型的“单例”模式(其中一个类应该只存在一个实例)。
它是在 TypeScript 中,但只需删除类型注释,它就可以在 JS 中工作。
// Only one instance can exist per application so the actual implementation class
// is hidden behind a Proxy (below). Thus we implement the singleton pattern.
class MySingletonImpl {
constructor() { /* ... */ }
}
var instance: MySingletonImpl | null = null;
// Proxy the implementation's constructor to ensure only one instance ever exists.
export const MySingleton = new Proxy(MySingletonImpl, {
construct(target, args) {
if (!instance)
instance = new target(...args);
return instance;
}
});
VSCode 至少足够智能,可以看到代理,并且仍然为实际实现类的成员提供完整的提示/检查支持。不过不知道其他编辑器怎么样。