拦截对构造函数的调用

问题描述 投票:0回答:4

我在拦截对库的构造函数调用时遇到了一些麻烦(这样我可以稍后重播它们),同时仍然维护原型链。更具体地说,我正在使用一个库(ThreeJS,但可以是任何库),以及一些使用该库的代码。我想做的是编写一段修改库对象的代码,这样我就可以在每次调用构造函数时运行一段代码。

示例:当创建一个新场景时,我想将“new Scene created”打印到控制台。

var scene = new THREE.Scene();

当构造函数接受参数时,我也想记录这些参数。

javascript prototype prototype-chain
4个回答
6
投票

我对此不确定,但是...你可以尝试类似...

// 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);

1
投票

使用代理:

THREE.Scene = new Proxy(THREE.Scene, {
    construct(target, args) {
        console.log(`creating a ${target.name} with ${args}`);
        return new target(...args);
    }
});

0
投票

从@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:", ....

0
投票

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 至少足够智能,可以看到代理,并且仍然为实际实现类的成员提供完整的提示/检查支持。不过不知道其他编辑器怎么样。

© www.soinside.com 2019 - 2024. All rights reserved.