Node.js中类循环依赖导致TypeError: Page1 is not a constructor错误
循环引用导致的构造函数错误问题及解决方法
问题背景
你使用了如下类结构:
- 根类
BasePage - 两个继承自
BasePage的子类Page1和Page2,二者互相引用并在方法中实例化对方
代码示例
BasePage.js
class BasePage { constructor() { this.root = "rootbase"; } } module.exports = BasePage;
Page1.js
const Page2 = require('./page2') const BasePage = require("./basePage") class Page1 extends BasePage { constructor() { super(); this.root = "root1"; } open2() { global.plop = new Page2() } } module.exports = Page1;
Page2.js
const Page1 = require('./page1') const BasePage = require("./basePage") class Page2 extends BasePage { constructor() { super(); this.root = "root2"; } open1() { global.plop = new Page1() } } module.exports = Page2;
执行代码
global.plop = new BasePage(); global.plop = new Page1(); plop.open2(); plop.open1();
错误信息
Uncaught TypeError TypeError: Page1 is not a constructor at open1 (c:\Users\Amira\Projects\nodetemp\page2.js:10:17) at main (c:\Users\Amira\Projects\nodetemp\index.js:11:10) at <anonymous> (c:\Users\Amira\Projects\nodetemp\index.js:15:1) at Module._compile (internal/modules/cjs/loader:1159:14) at Module._extensions..js (internal/modules/cjs/loader:1213:10) at Module.load (internal/modules/cjs/loader:1037:32) at Module._load (internal/modules/cjs/loader:878:12) at executeUserEntryPoint (internal/modules/run_main:81:12) at <anonymous> (internal/main/run_main_module:23:47)
问题原因
这是CommonJS模块循环引用导致的问题:
Node.js加载CommonJS模块时,会优先加载模块的依赖。当Page1启动加载时,会触发Page2的加载;而Page2加载时又会反向加载Page1,此时Page1还未完成类的定义与导出,所以Page2拿到的Page1是一个未初始化的空对象,并非构造函数,调用new Page1()自然会报错。
解决方法
方法1:延迟加载模块
将模块的require语句从模块顶部移到方法内部,仅在方法执行时才加载目标模块,此时两个模块都已完成初始化:
修改后的Page1.js:
const BasePage = require("./basePage") class Page1 extends BasePage { constructor() { super(); this.root = "root1"; } open2() { const Page2 = require('./page2'); global.plop = new Page2() } } module.exports = Page1;
修改后的Page2.js:
const BasePage = require("./basePage") class Page2 extends BasePage { constructor() { super(); this.root = "root2"; } open1() { const Page1 = require('./page1'); global.plop = new Page1() } } module.exports = Page2;
方法2:重构代码消除循环依赖
提取公共逻辑到第三方模块,让Page1和Page2不再直接互相引用:
创建pageManager.js:
const Page1 = require('./page1'); const Page2 = require('./page2'); class PageManager { static openPage1() { global.plop = new Page1(); } static openPage2() { global.plop = new Page2(); } } module.exports = PageManager;
修改后的Page1.js:
const BasePage = require("./basePage") const PageManager = require('./pageManager'); class Page1 extends BasePage { constructor() { super(); this.root = "root1"; } open2() { PageManager.openPage2(); } } module.exports = Page1;
修改后的Page2.js:
const BasePage = require("./basePage") const PageManager = require('./pageManager'); class Page2 extends BasePage { constructor() { super(); this.root = "root2"; } open1() { PageManager.openPage1(); } } module.exports = Page2;
方法3:切换到ES模块
Node.js对ES模块(import/export)的循环引用处理更完善,你可以:
- 将文件扩展名改为
.mjs - 或者在
package.json中添加"type": "module" - 把
require/module.exports替换为import/export
这种方式适合新项目,需要统一调整模块系统。
内容的提问来源于stack exchange,提问作者sarut0bi
相关产品推荐
相关产品推荐

