Javascript 为什么我导出的函数不是函数?
考虑以下示例:Javascript 为什么我导出的函数不是函数?,javascript,node.js,Javascript,Node.js,考虑以下示例: // bar.js const foo = require('./foo'); module.exports = function(args){ let f = foo(args) } // foo is not a function 然后: foo.js看起来像: const bar = require('./bar'); module.exports = function(args){ //same args as bar.js const f
// bar.js
const foo = require('./foo');
module.exports = function(args){
let f = foo(args)
}
// foo is not a function
然后:
foo.js看起来像:
const bar = require('./bar');
module.exports = function(args){ //same args as bar.js
const foo = {};
foo.f1 = function(arg){
console.log("Hi")
}
return foo
};
您正在处理循环依赖的问题。我猜
foo.js
看起来像这样:
const bar = require('./bar');
module.exports = function(args) {
console.log(args);
};
让我们遵循VM执行代码的步骤(假设您首先加载foo.js
):
foo.js
。使用A={}
初始化导出bar.js
。使用B={}
初始化导出。现在在bar.js中
:
bar.js
需要导出foo.js
(仍然是A={}
),所以将bar.js
中的foo
设置为A={}
(这就是问题所在!)bar.js
foo.js
的导出bar.js
中foo.js
的导出
在第二个示例中,稍后在调用函数时解析foo.js
的导出。此时,foo.js
的导出已经被函数替换,并且可以正常工作
简短的版本:这就是发生的事情
foo.js
,并使用对象A
初始化foo.js
的导出bar.js
,并使用对象B
初始化bar.js
的导出bar.js
中的变量foo
设置为foo.js
的导出,因此foo=A
C
取代了导出的bar.js
foo.js
中的变量bar
设置为导出bar.js
,因此bar=C
D
替换foo.js
的导出bar.js
中的变量foo
仍然是A
,即使它应该是D
您通常希望避免使用循环依赖关系。如果确实需要,则不要替换
模块。导出
,而是将属性附加到对象:
module.exports.doBarAction = function(args){
let f = foo.doFooAction(args)
};
这解决了问题,因为对象在运行时仍然是相同的。然而,在大多数情况下,最好摆脱循环依赖,至少在我们讨论CommonJS模块时是这样。foo的代码肯定不是“不必要的代码”。我更新了更多的问题code@znat是的,这正是我所期望的,关于解释和解决方案,请参阅我的答案。这对于Java程序员来说很难理解:)@znat是的,Java执行静态编译,允许编译器毫无问题地解决循环依赖关系,但JavaScript VM没有。不要试图将
require()
与import
进行比较。
module.exports.doBarAction = function(args){
let f = foo.doFooAction(args)
};