首先让我说这更像是一个好奇的问题,因为正如您将看到的那样,我能够实现所需的功能。
然而,鉴于 javascript 是一种 super 灵活的语言,我想看看其他开发者可能会如何看待这个问题:
我有一个从 vendor 函数返回的类的实例:
const connection = vendorDatabaseLib.createConnection();
现在,我想创建一个装饰器,它将向连接类添加功能,例如重新连接逻辑。
让我们称之为 PersistentConnection
。除了我添加的自定义函数外,我还想要一个 PersistentConnection
实例,以将所有函数调用转发到原始 Connection
实例。并且在某些函数中覆盖行为。
我当然可以显式实现所有 Connection
的功能并将它们转发给内部对象,但可能有很多这样的功能,所以我很快放弃了这个想法。
所以这里是我如何实现这一点的想法:
- Monkey 修补 🐒,我可以创建一个
PersistentConnection
类,它继承自 vendorConnection
,然后修补 vendorvendorDatabaseLib.createConnection
函数返回PersistentConnection
以及我想要的所有附加功能。诱人,但不好。 - 创建一个装饰器,它迭代
Connection
函数并动态创建转发,类似于:
class PersistentConnection{
constructor(connection){
this._connection = connection;
// Iterate through all functions
for (prop in this._connection){
if(typeof(this._connection[prop]) === 'function'){
// Create functions dynamically for each forward
this[prop] = (...args) => {
this._connection[prop](...args);
}
}
}
}
// This is the added logic
reconnect(){
// Custom logic
}
}
- 将
Connection
实例设置为PersistentConnection
实例的原型(prototype):
function persistenChannel(channel){
const persistentChannel = {};
Object.setPrototypeOf(persistentChannel, channel);
persistentChannel.reconnect = () => {
// custom logic
}
}
这是我能想到的最“自动”的方式。但它实在是太丑了,每次创建实例时都需要声明自定义函数。
我仍然觉得我遗漏了一些东西,比如 Ruby 神奇的 method_missing
(或 pythons __getattr__
)函数,它在 方法丢失之前被调用
抛出异常并允许您定义“安全网”逻辑(例如将所有调用委托(delegate)给内部 _connection
对象。
有没有更好的方法来实现这个功能?
非常感谢[=
最佳答案
让我们从现有的开始。在任何情况下,大部分功能将由 vendor 对象执行。我们不知道实现的细节,所以我们不能相信这个对象没有状态。这意味着,在任何情况下,我们都需要为新的持久连接创建新 连接对象。这可以通过 proxy object 来实现
让我们尝试这样做:
function Connection() {
this.connect = () => console.log('connected by Connection class');
this.disconnect = () => console.log('disconnected by Connection class');
}
function persistantConnectionFactory() {
function PersistentConnection() {
this.checkConnection = () => console.log('no connection');
}
const instance = new PersistentConnection();
const proxy = new Proxy(instance, {
get: function (target, name) {
if (!(name in target)) {
console.log('adding new prototype')
Object.setPrototypeOf(instance, new Connection())
}
return target[name];
}
});
return proxy;
}
var c = persistantConnectionFactory();
c.checkConnection();
c.connect();
这个解决方案好吗?我想不是。如果没有很好的理由,这会增加复杂性而没有任何值(value)。原型(prototype)应该足够了。
关于javascript - 在不显式转发所有函数的情况下装饰类实例,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45325524/