类型错误:类扩展值未定义不是构造函数或 null

Owe*_*ath 11 javascript node.js

在过去的几天里,这个问题一直让我失去理智。

这是我的目录结构:

[src]
|- cmds/
|  |- Gh.js
|  \- Help.js
|- commands.js
|...
Run Code Online (Sandbox Code Playgroud)

我试图通过导入导出的类commands.jsHelp.jsGh.js(以及任何其他文件,我可能会在未来增加)。但是,我不断收到错误消息:

class Gh extends _commands.Command {
                           ^
TypeError: Class extends value undefined is not a constructor or null
Run Code Online (Sandbox Code Playgroud)

所有文件都使用 Babel 进行转译,env设置为"node": "current"并使用wildcard包。我试图设置它"browser"以查看是否是它过于“高级”的问题,但是我对超级函数(或其他东西)有一个不同的错误,我认为这是同一个问题。

这是从commands.js以下导出的类:

[src]
|- cmds/
|  |- Gh.js
|  \- Help.js
|- commands.js
|...
Run Code Online (Sandbox Code Playgroud)

...这是cmds/Gh.js我试图导入的文件之一Command

class Gh extends _commands.Command {
                           ^
TypeError: Class extends value undefined is not a constructor or null
Run Code Online (Sandbox Code Playgroud)

我尝试将Command两者都放入cmds/,并且它们工作得很好。然而,当把它移回 时commands.js,它又坏了。我尝试将其导入的路径从 from../commands更改为./../commands, ../commands.js, ./../commands.js; 没有一个工作。我搬进commands.js去了cmds/,还是破了。我试图console.log(Command)在两者中cmds/,但它们都返回了undefined

所有这一切使它看起来像是导入的问题,但我无法弄清楚我的生活是什么。请帮忙。

MBe*_*Ber 27

如果其他人看到此错误,首先要查找的是循环依赖项。将文件 A 导入 B,将 B 导入其他文件 C,依此类推。如果将 C 到 Z 中的任何一个导入到 A 中,那么 JS 将无法确保在另一个文件需要它时定义了一个文件(并且以后不会尝试返回并填充空白)。

这很可能是这里的情况,因为显然没有发布其他代码,并且只有在引入文件依赖项时才会出现。无论文件结构如何,问题都存在:唯一保证避免它的结构是单个巨大的 JS 文件。解决方案是确保类之间关系的严格树结构,并使用工厂方法或替代通信(如发射器)来保持耦合松散。

如果您有多个 import / require 语句,我建议定期运行像Madge这样的检查器来查找并可选地可视化任何循环,以免它们变得难以撤消。

npm install --save-dev madge
node_modules/madge/bin/cli.js --warning --circular --extensions js ./
Run Code Online (Sandbox Code Playgroud)


Jos*_*sen 12

正如其他人提到的,这是循环依赖造成的。我尝试了几个小时来解决它。最终,一个名为dpdm的工具为我带来了奇迹,找到了 27 个周期并迅速解决了问题。(我只需要解决其中的几个问题即可解决其余的问题。)

yarn global add dpdm或者npm i -g dpdm

然后 dpdm file.js或者dpdm file.ts

就我而言,这发现了 Madge 和手动检查未能揭示的大量周期。很棒的工具。


小智 5

这只是对 Node.js 的简单修复。从您的班级中删除导出,并将其放入文件底部。

module.exports.Command;
Run Code Online (Sandbox Code Playgroud)

现在,如果您想在任何地方使用命令类,您只需将其放入您想要使用它的每个文件中。

var { Command } = require('Command.js');
Run Code Online (Sandbox Code Playgroud)