javascript - 在使用来自深度 npm 依赖项的构造函数创建的对象上使用 `instanceof`

标签 javascript node.js npm

背景:

我有一个 npm 模块,其中包含常见的错误处理代码,包括自定义错误:

function CustomError () { /* ... */ }
CustomError.prototype = Object.create(Error.prototype);
CustomError.prototype.constructor = CustomError;
module.exports = CustomError;

我还有一些其他模块(我们称它们为 'module-a''module-b'),它们都依赖于错误处理模块。

我还有一些使用 Bluebirds“过滤捕获”功能的代码:

doSomething
.catch(CustomError, () => { /* ... */ });

问题:

经过一些调试后,我发现(事后看来有些明显)在 'module-a' 中创建的错误不是 'module-b' 创建的错误实例>。这是因为两个模块都有自己的 JS 文件副本,其中包含 CustomError 构造函数,它们都是独立运行的。

我宁愿不必求助于我目前的解决方案,基本上是:

CustomError.isCustomError = e => e.constructor.toString() === CustomError.toString();

然后:

doSomething
.then(CustomError.isCustomError, () => { /* ... */ });

这显然是脆弱的,如果版本不同步就会崩溃。

所以...

有没有办法确保 'module-a''module-b' 都使用相同的构造函数实例?或者另一种不那么脆弱的解决方案。

最佳答案

这实际上也是浏览器中的一个问题,当您拥有一个 iframe 时,它​​会获得自己的副本,例如 Array 构造函数(使 instanceof 无用)。

自定义构造函数的解决方案是鸭式。以下是一些具有优缺点的潜在解决方案。

  1. 检查构造函数名称。优点:简单,支持良好。缺点:最好选择一个相当独特的名称,以避免误报并忘记对其进行子分类。

  2. 检查对象的属性(例如,同时具有 'foo' 和 'bar 并且 'foo' 是一个函数)。优点:大多是万无一失的。缺点:脆弱:如果您重构自定义错误类,此检查可能会随机中断,相对昂贵。

  3. (推荐)添加属性/方法。这就是许多库(例如,moment.js)处理此问题的方式。

代码示例:

CustomError.prototype._isCustomError = true;
var isCustomError = function isCustomError(obj) {
  return obj instanceof CustomError || Boolean(obj._isCustomError);
};

module.exports = {
  CustomError,
  isCustomError
};

这或多或少正是 moment 检测给定对象是否为 moment 对象的方式。

关于javascript - 在使用来自深度 npm 依赖项的构造函数创建的对象上使用 `instanceof`,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41587865/

相关文章:

javascript - 回车键模拟jquery/js(chrome脚本)

npm - 500 内部服务器错误 : npm@latest

javascript - 在新的 vue 项目上运行 npm run serve 时出错

node.js - 转发端口从 80 和 443 到 8080

MySQL 与 Node.js

javascript - 为什么在使用 "Environment Variable"时将 API key 存储在 DigitalOcean API "App Platform"选项中是安全的?

node.js - npm uninstall 从 package.json 中删除包,但不会从 node_modules 文件夹中删除

javascript - css3 动画表现不佳(仅限 Chrome)

javascript - 删除 Google Maps Api v3 中的标记

javascript - 如何将模型对象数组转换为以模型 ID 作为键的对象?