gpt4 book ai didi

javascript - 为什么我导出的函数不是函数?

转载 作者:太空宇宙 更新时间:2023-11-04 00:27:55 25 4
gpt4 key购买 nike

考虑以下示例:

// bar.js
const foo = require('./foo');

module.exports = function(args){
let f = foo(args)
}
// foo is not a function

然后:

// bar.js
module.exports = function(args){
let f = require('./foo')(args)
}
// behaves as expected

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);
};

让我们按照虚拟机执行的步骤来执行代码(假设您首先加载 foo.js):

  1. 加载foo.js。使用 A = {} 初始化导出。
  2. 加载bar.js。使用 B = {} 初始化导出。现在在 bar.js 中:
    1. bar.js 需要 foo.js 的导出(仍然是 A = {}),因此设置 foo bar.js 中的 A = {}(这就是问题所在!)。
    2. bar.js 的导出替换为声明的函数。
  3. foo.js 的导出替换为声明的函数。

如您所见,如果您使用循环依赖项,虚拟机将无法跟踪 bar.jsfoo.js 的导出。

在第二个示例中,稍后在调用该函数时解析 foo.js 的导出。此时,foo.js 的导出已被该函数替换,并且可以正常工作。

<小时/>

简短版本:这就是发生的事情。

  1. 虚拟机加载 foo.js 并使用对象 A 初始化 foo.js 的导出。
  2. 虚拟机加载 bar.js 并使用对象 B 初始化 bar.js 的导出。
  3. VM 将 bar.js 中的变量 foo 设置为 foo.js 的导出,因此 foo = A
  4. VM 将 bar.js 的导出替换为函数 C
  5. VM 将 foo.js 中的变量 bar 设置为 bar.js 的导出,因此 bar = C
  6. 虚拟机将 foo.js 的导出替换为函数 D

正如您再次看到的,bar.js 中的变量 foo 仍然是 A,尽管它应该是 D .

<小时/>

您通常会希望避免使用循环依赖项。如果确实有必要,则不要替换 module.exports,而是将属性附加到对象:

module.exports.doBarAction = function(args){
let f = foo.doFooAction(args)
};

这解决了问题,因为对象在运行时仍然相同。
然而,在大多数情况下,最好摆脱循环依赖,至少在我们谈论 CommonJS 模块时是这样。

关于javascript - 为什么我导出的函数不是函数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42093712/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com