ES 编码实践 —— 拓展已有方法

published

情境

偏底层的数据库包,很少封装业务逻辑相关的内容,比如创建时间、更新时间。 如果想要在每次更新数据库时,同时更新「更新时间」。要怎么办呢?

常见的解决方法

  • 方法 1:调用具体的更新方法时,手动添加更新时间。
  • 方法 2:覆写更新方法,使方法被调用时,自动添加更新时间。

为了减少繁冗的代码,当然会选择方法 2。

代码

错误的代码

// db.update 为数据库更新方法
db.update = async function (table, row, options) {
  row.updated_at = app.mysql.literals.now

  return Reflect.apply(db.update, this, [ table, row, options ])
}

db.update 指向的对象被直接修改。 return Reflect.apply(db.update, this, [ table, row, options ]) 中的 db.update 指向修改后的函数,这会造成循环调用。

正确的代码

// db.update 为数据库更新方法
db.update = (function (_super) {
  return async function (table, row, options) {
    row.updated_at = app.mysql.literals.now

    return Reflect.apply(_super, this, [ table, row, options ])
  }
})(db.update)

通过闭包将 db.update 所指向的原始函数对象保存在 Reflect.apply(_super, this, [ table, row, options ]) 的作用域链中,并通过 _super 调用。

总结

利用闭包拓展已有方法。