javascript - 在不显式转发所有函数的情况下装饰类实例

标签 javascript

首先让我说这更像是一个好奇的问题,因为正如您将看到的那样,我能够实现所需的功能。
然而,鉴于 javascript 是一种 super 灵活的语言,我想看看其他开发者可能会如何看待这个问题:

我有一个从 vendor 函数返回的类的实例:

const connection = vendorDatabaseLib.createConnection();

现在,我想创建一个装饰器,它将向连接类添加功能,例如重新连接逻辑。
让我们称之为 PersistentConnection。除了我添加的自定义函数外,我还想要一个 PersistentConnection 实例,以将所有函数调用转发到原始 Connection 实例。并且在某些函数中覆盖行为。
我当然可以显式实现所有 Connection 的功能并将它们转发给内部对象,但可能有很多这样的功能,所以我很快放弃了这个想法。

所以这里是我如何实现这一点的想法:

  1. Monkey 修补 🐒,我可以创建一个 PersistentConnection 类,它继承自 vendor Connection,然后修补 vendor vendorDatabaseLib.createConnection 函数返回 PersistentConnection 以及我想要的所有附加功能。诱人,但不好。
  2. 创建一个装饰器,它迭代 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
  }
}

  1. 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/

相关文章:

javascript - jQuery.validate,具有多个条件的表单

javascript - 使用 jquery 更改 css 而不会出现任何过渡

javascript - 使用 jQuery,如何获取元素的文本值?

javascript - 顺序主干 model.set 覆盖 model.changed 属性

javascript - JSPDF - 如何将具有不同页面大小(高度和宽度)的多个图像导出到单个 pdf 文件

javascript - 在 typescript 中 trim 特殊字符之前获取输入[文本]值

javascript - 如何允许最终用户为此模式定义多个 namespace 扩展级别?

javascript - JavaScript 中的对象引用比较

javascript - 在 dojo 中使用 this 通过父类访问子方法

javascript - 在网站的移动版本中集成 OAuth 工作流