导出ES6 Javascript的文件范围变量
接下来,我知道可能有也可能没有所谓的文件范围变量,但是,我确实记得在某个地方读过这样的术语,但除了的Q&a之外,我再也找不到了。反正 我想知道这种导出的文件范围变量的确切行为定义是什么 因为我试图动态切换我的机器人,但无法,一个接一个地消除了各种因素,最终它落在了我的头上,这是因为这些“导出的文件范围变量”,而我不理解它们的行为。请看以下极其简化的bot应用程序: VarTestFileA.js导出ES6 Javascript的文件范围变量,javascript,ecmascript-6,es6-modules,Javascript,Ecmascript 6,Es6 Modules,接下来,我知道可能有也可能没有所谓的文件范围变量,但是,我确实记得在某个地方读过这样的术语,但除了的Q&a之外,我再也找不到了。反正 我想知道这种导出的文件范围变量的确切行为定义是什么 因为我试图动态切换我的机器人,但无法,一个接一个地消除了各种因素,最终它落在了我的头上,这是因为这些“导出的文件范围变量”,而我不理解它们的行为。请看以下极其简化的bot应用程序: VarTestFileA.js function nextBot() { BotC = !BotC return BotA[
function nextBot() {
BotC = !BotC
return BotA[BotC]
}
function logBot() {
console.log("I:", bot)
}
const BotA = {true: {"token": 2}, false: {"token":3}}
let BotC = true
var bot = BotA[BotC]
module.exports = {
bot,
nextBot,
logBot,
}
const bt = require('./VarTestFileA')
console.log(bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
VarTestFileB.js
function nextBot() {
BotC = !BotC
return BotA[BotC]
}
function logBot() {
console.log("I:", bot)
}
const BotA = {true: {"token": 2}, false: {"token":3}}
let BotC = true
var bot = BotA[BotC]
module.exports = {
bot,
nextBot,
logBot,
}
const bt = require('./VarTestFileA')
console.log(bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
bt.bot = bt.nextBot()
bt.logBot()
console.log("O:", bt.bot)
您可能知道(即使不运行它),无论我如何操作,bt.bot
都无法切换。以下是输出:
$ node VarTestFileB.js
{ token: 2 }
I: { token: 2 }
O: { token: 3 }
I: { token: 2 }
O: { token: 2 }
I: { token: 2 }
O: { token: 3 }
另外,我尝试从VarTestFileA.js
中切换bot
,它在其中工作,但是console.log(“O:,bt.bot.token)
从不显示更新的值。所有的一切
这一切都归结为导出的文件范围变量的精确行为定义,因为如果将它们放在同一个文件中,它运行得非常好。因此问题就来了。这种行为非常直截了当,同时也非常有趣。语句
const bt=require('./VarTestFileA')
创建导出对象的对象副本,我们使用变量的地方(例如bot
)-传递值而不是引用,但传递函数的地方传递引用,因为函数是JS中的对象
我们从VarTestFileA.js导出了{bot,nextBot,logBot}
,因此dt
实际上等于:
dt = {
bot : bot, //copy of old bot = BotA[BotC] which equals {"token": 2}
nextBot: nextBot, //reference to nextBot() which has access to bot in file A
nextBot: logBot , //reference to logBot () which has access to bot in file A
}
现在来看VarTestFileB.js,在这里我们打印并试图理解其行为,让我们看看每个语句的行为:
第一句话:
console.log(bt.bot)
将打印{“token”:2}
,因为bot
是通过值传递的,而不是引用
第二句话:
bt.bot=bt.nextBot()
这实际上更改了dt.bot
的值,而不是文件A中的真实bot
。因此bt.bot
将具有切换值,但文件A中声明的实际bot
仍然相同,因为它没有更改。现在我们来看第三种说法:
第三句话:
bt.logBot()
,这将打印文件A中的bot
的初始值,因为它尚未更改
所以这里真正的答案是,基于这种行为,我们可以声明,如果我们在文件A中保存变量的引用,那么我们可以从另一个文件中更改它们。但我真的能提供证据吗?好!是的,让我们看看下面的内容
为了测试这一点,让我们在文件A中创建另一个方法
function getBot(){
return bot;
}
然后修改nextBot
,如下所示:
function nextBot() {
BotC = !BotC
bot = BotA[BotC]
}
{ token: 2 }
I: { token: 3 }
O: { token: 3 }
I: { token: 2 }
O: { token: 2 }
I: { token: 3 }
O: { token: 3 }
然后导出对这些方法的引用
module.exports = {
getBot,
nextBot,
logBot,
}
因此,我们现在可以执行相同的实验,并尝试打印出问题中的旧测试:
const bt = require('./VarTestFileA')
console.log(bt.getBot())
bt.nextBot()
bt.logBot()
console.log("O:", bt.getBot())
bt.nextBot()
bt.logBot()
console.log("O:", bt.getBot())
bt.nextBot()
bt.logBot()
console.log("O:", bt.getBot())
输出如下:
function nextBot() {
BotC = !BotC
bot = BotA[BotC]
}
{ token: 2 }
I: { token: 3 }
O: { token: 3 }
I: { token: 2 }
O: { token: 2 }
I: { token: 3 }
O: { token: 3 }
结果很有趣,因为现在来自文件A的bot
似乎正在按预期进行切换
总之,问题在于通过引用或值传递属性<代码>机器人
从您的初始代码作为值传递,它不是一个复杂的项目,或者它不是声明为类型对象
,而是作为值保存一个简单的对象。因此,无法通过引用传递bot
。我希望得到纠正,但我不认为JavaScript中包含基本值(如布尔值)的变量或简单对象可以通过引用传递。但函数是复杂类型,这意味着它们是对象
s,因此它们是通过引用传递的
我希望您能找到正确的答案。您能为每个实例提供console.log的输出吗?谢谢,让我快速解释一下为什么会发生这种行为。我不在!我花了一些时间来写答案,我有点忙,但我已经在下面提供了答案,解释了如何使用切换机器人并始终获得其更新值的行为和解决方法。始终是一个喜悦@xpt,我很高兴我能在这个主题上提供一些帮助。