【问题标题】:avoid hacks to properly bind to class in ES6?避免黑客正确绑定到 ES6 中的类?
【发布时间】:2017-05-11 08:45:13
【问题描述】:

我觉得这很麻烦。我可能做错了,或者有一些我不知道的更简单的方法(在不知道要搜索什么的情况下找不到太多)。

我想避免执行以下两种变通方法,以确保 this 正确指向我的方法中的 DB 类:

this.connect = this.connect.bind(this);
db.connect.bind(db)

数据库类:

'use strict';

const http = require('http');
const MongoClient = require('mongodb').MongoClient;

class DB {
  constructor(opts){
    this.opts = opts;
    this.dbUrl = process.env.MONGODB_URL;

    // anyway to avoid this hacK?
    this.connect = this.connect.bind(this);
    this.close = this.close.bind(this)
  }

  async connect(ctx, next){
    try {
      ctx.db = await MongoClient.connect(this.dbUrl); // fixes `this` being incorrect here
    } catch(err) {
      ctx.status = 500;
      ctx.body = err.message || http.STATUS_CODES[ctx.status];
    }

    await next();
  }

  async close(ctx, next){
    const result = await ctx.db.close();
    await next();
  }
}

module.exports = DB;

调用DB类方法db.connect()

'use strict';

const Koa = require('koa');
const DB = require('./db');
const db = new DB();
const bodyParser = require('koa-bodyparser');
const router = require('koa-router');

const api = router();
const app = new Koa();
const cors = require('kcors');

app
  .use(bodyParser())
  .use(cors())
  .use(db.connect); // the above constructor copying fixes having to do `db.connect.bind(db)` here

  // without the constructor fix in class DB:

  .use(db.connect.bind(db)) // this gets annoying having to do this everywhere

哪个更“正确”或者是否有第三种方法可以避免这两种解决方法?如果只有这两种方法可以将类方法绑定到它们的类,那么每种方法的优缺点是什么。

【问题讨论】:

  • 另一种不那么骇人听闻的方式是在外壳中,即app.use((...args) => db.connect(...args))
  • async connect(){} 方法中正确获取this 似乎非常冗长......如果我理解正确,仍然不会将其更改为DB
  • 严肃的问题:使用bind() 真的被认为是一种黑客行为吗?我一直认为这是在丢失上下文时绑定上下文的好方法。我知道替代方法是使用胖箭头函数(() => {...})或将上下文分配给您通过闭包访问的变量(例如,var contextvar _thisvar thatvar self)...但是对于我,bind() 通常是最简洁合理的方式。
  • 这是我被告知的“正确”方式(不知道这种特定情况是否适用于“最好/最简单的方式”),但是当每个当您在代码库中调用类实例的方法时,您必须将其绑定到自身。
  • @chovy 我想你可能会觉得stackoverflow.com/a/32192892/3814251 是一个有趣的潜在解决方案

标签: javascript ecmascript-6 es6-class


【解决方案1】:

有一系列有用的自动绑定功能。我今天写了一篇来改进它们。看一看:https://www.npmjs.com/package/auto-bind-inheritance

npm install --save auto-bind-inheritance

const autoBind = require('auto-bind-inheritance');

只需将autoBind(this); 放入子类构造函数中,所有方法和方法指针都将绑定到该对象,就像您在C++/Java 中所期望的一样。这基本上会为您调用bind

因此,如果您在将方法用作绑定到另一个“this”的回调时遇到问题,这个包将解决它。

【讨论】:

    猜你喜欢
    • 2015-11-18
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    • 1970-01-01
    • 2020-10-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多