关于javascript:如何在switch语句中使用instanceof

How to use instanceof in a switch statement

我使用自定义错误(ES6错误),允许我根据类处理错误,如下所示:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      if (error instanceof DatabaseEntryNotFoundError) {
        return res.send(404);
      } else if (error instanceof NotAllowedError) {
        return res.send(400);
      }
      log('Failed to do something async with an unspecified error: ', error);
      return res.send(500);
    };
}

现在,我更愿意为这种类型的流使用一个开关,结果是:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import { DatabaseEntryNotFoundError, NotAllowedError } from 'customError';

function fooRoute(req, res) {
  doSomethingAsync()
    .then(() => {
      // on resolve / success
      return res.send(200);
    })
    .catch((error) => {
      // on reject / failure
      switch (error instanceof) {
        case NotAllowedError:
          return res.send(400);
        case DatabaseEntryNotFoundError:
          return res.send(404);
        default:
          log('Failed to do something async with an unspecified error: ', error);
          return res.send(500);
      }
    });
}

但InstanceOf并不像那样工作。所以后者失败了。

在switch语句中有没有方法检查实例的类?


一个好的选择是使用对象的constructor属性:

1
2
3
4
5
6
7
8
9
10
// on reject / failure
switch (error.constructor) {
    case NotAllowedError:
        return res.send(400);
    case DatabaseEntryNotFoundError:
        return res.send(404);
    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}

注意,constructor必须与创建对象的完全匹配(假设errorNotAllowedError的实例,NotAllowedErrorerror的子类):

  • error.constructor === NotAllowedErrortrue
  • error.constructor === Errorfalse

这与instanceof有所不同,后者也可以与超级类相匹配:

  • error instanceof NotAllowedErrortrue
  • error instanceof Errortrue

查看有关constructor属性的有趣文章。


解决方法,以避免其他情况。在这里找到

1
2
3
4
5
6
7
8
9
10
11
switch (true) {
    case error instanceof NotAllowedError:
        return res.send(400);

    case error instanceof DatabaseEntryNotFoundError:
        return res.send(404);

    default:
        log('Failed to do something async with an unspecified error: ', error);
        return res.send(500);
}


另一种情况是在错误的构造函数中只包含一个状态字段。

例如,像这样构建错误:

1
2
3
4
5
6
7
class NotAllowedError extends Error {
    constructor(message, status) {
        super(message);
        this.message = message;
        this.status = 403; // Forbidden error code
    }
}

像这样处理错误:

1
2
3
.catch((error) => {
  res.send(error.status);
});