You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何通过require引入的函数在类实例中调用时返回undefined?

问题原因

你遇到的是Node.js的*循环依赖(循环引用)*问题,和类、模块的访问机制无关,也不是语法类低级错误。
你的两个模块形成了互相引用的关系:

  1. Site.js 顶层通过 require('../DataFunctions.js') 加载数据工具模块
  2. DataFunctions.js 顶层又通过 require('./classes/Site.js') 加载Site类模块
    Node.js处理CommonJS模块循环引用时,会先给正在加载的模块返回未完成的导出对象作为占位,等模块代码全部执行完再补全导出内容。你当前的执行路径是DataFunctions先加载Site,Site加载到一半又回头加载还没执行完导出逻辑的DataFunctions,所以Site里拿到的dataFunctions就是未初始化完成的占位对象,最终表现为undefined。

其他疑问解答

  • 只要Page.js没有和其他模块形成循环依赖,Site类可以正常引用Page类,无任何问题
  • Site类的实例本身有权限访问正确加载后的dataFunctions模块,问题出在模块加载顺序而非访问权限

解决方案

方案1:移除不必要的循环依赖(最推荐)

将DataFunctions中依赖Site类的实例创建逻辑抽离到单独的业务文件,从根源消除循环引用:

  1. 修改DataFunctions.js,删除顶层的Site引用:
// 删除 let Site = require('./classes/Site.js'); 这行代码
function getSiteInfo(id) {
    // 原有查询逻辑
}

module.exports = {
    getSiteInfo: function (id) {
        return getSiteInfo(id);
    },
};
  1. 新建SiteFactory.js统一处理Site实例创建:
let Site = require('./classes/Site.js');
let dataFunctions = require('./DataFunctions.js');

function makeASite() {
    let id = 2;
    let site = new Site(id);
    return site;
}
module.exports = { makeASite };

方案2:延迟加载模块,避开初始化阶段的循环引用

如果暂时不想调整代码结构,可以将模块引用的时机后移到模块初始化完成之后:
修改Site.js,将dataFunctions的引入放到构造函数内部:

let Page = require('./Page.js');
// 删除顶层的dataFunctions引入代码

module.exports = class Site {
    constructor(id) {
        this.id = id;
        this.pages = [];
        // 构造函数执行时DataFunctions已经完成初始化,此时引入可以拿到完整的导出对象
        const dataFunctions = require('../DataFunctions.js');
        console.log(dataFunctions);
        this.siteInfo = dataFunctions.getSiteInfo(id);
    }
}

内容的提问来源于stack exchange,提问作者Daniel

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.01 16:36:02