' TypeError:undefined不是函数'在模块之间跳转时

时间:2015-08-03 09:09:38

标签: javascript node.js typeerror

我一直在Node中遇到这个问题,每当我调用彼此的函数时,我的应用程序就会崩溃。

我已经做了这个最小的工作示例(因为它给我的错误):

启动模块

var module2 = require('./module2');

var data = 'data';

module2.doStuff(data);

单词数

var module3 = require('./module3');

function doStuff(data){
    // Stuff happens to 'data'
    module3.takeStuff(data);
}

function doSomethingElse(data){
    console.log(data);
}


module.exports = {
    doStuff: doStuff,
    doSomethingElse: doSomethingElse
};

单词数

var module2 = require('./module2');

function takeStuff(data){
    // Stuff happens to 'data'
    module2.doSomethingElse(data); // I get the type error here
}

module.exports = {
    takeStuff: takeStuff
};

我得到的错误是:

module2.doSomethingElse(data); // I get the type error here
        ^
TypeError: undefined is not a function

start module调用module2中的一个函数,最终调用module3中的函数,该函数又调用module2中的函数。

所有模块都是正确需要的,它会在module2中找到第一种方法。

这里发生了什么?如果需要从模块中获取功能,那么如何处理这种模式呢?

修改

调试显示模块存在,但它与原型相比是空的。我的问题是为什么?在Node / JavaScript里面,这里发生了什么?

2 个答案:

答案 0 :(得分:6)

这里的问题可以轻松解决,同时保持应用程序的结构(就循环引用而言,这很好)。

您只需要保留系统为模块提供的默认exports对象。请勿使用module.exports = {...}更改它。

以下内容应该有效:

启动模块

var module2 = require('./module2');

var data = 'data';

module2.doStuff(data);

第2单元

var module3 = require('./module3');

exports.doStuff = function doStuff(data){
    // Stuff happens to 'data'
    module3.takeStuff(data);
};

exports.doSomethingElse = function doSomethingElse(data){
    console.log(data);
};

第3单元

var module2 = require('./module2');

exports.takeStuff = function takeStuff(data){
    // Stuff happens to 'data'
    module2.doSomethingElse(data); // I get the type error here
};

说明

我会尝试解释从起点的第一行发生的事情:

  1. 在start.js中,您需要module2并且尚未加载:执行module2.js中的代码
  2. 在module2.js中,您需要module3且尚未加载:执行module3.js中的代码
  3. 在module3.js中,你需要module2,它已经加载了:module2变量现在包含来自module2的exports对象。
  4. 执行module3的其余部分,并使用module.exports = {...}
  5. 更改其导出对象
  6. 在module2.js中,module3变量现在包含来自module3的exports对象。
  7. 执行module2.js的其余部分,并使用module.exports = {...}
  8. 更改其导出对象
  9. 在start.js中,module2变量现在包含来自module2的exports对象。
  10. 这里的问题是在第3点和第6点之间。在更改对它的引用之前,Module3正在接收module2(3)的导出(6)。 使用exports.method = ...解决了问题,因为exports对象永远不会改变。

答案 1 :(得分:4)

你有一个循环引用,模块2依赖于模块3,模块3依赖于模块2,模块2依赖于模块3(依此类推)。因此,在尝试解析module 3 module 2时,它无法完成,因为module 3本身需要先解决。

来自https://nodejs.org/api/modules.html#modules_cycles

  

当有循环的require()调用时,模块可能没有   在返回时完成执行。

     

为了防止无限循环,a.js的未完成副本   exports对象返回到b.js模块。

因此该模块可用,但不完整(这说明您只接收原型)。循环引用无论如何都是代码味道,尽量避免使用它:)

但是,如果您将模块2和3都作为依赖项放在启动模块中,那么无论如何都应该可以正常工作。

var module2 = require('./module2');
var module3 = require('./module3');

var data = 'data';

module2.doStuff(data);