ES6 的导出文件范围变量 Javascript
Exported File Scope Variables of ES6 Javascript
跟进 , from which I know that there might or might not be a so-called File Scope Variables, however, I do remember reading such term somewhere but couldn't find it any more, except the Q&A of 。无论如何,
我想知道此类导出的文件范围变量的确切行为定义是什么。
因为我试图动态切换我的机器人但没能做到,一个一个地消除了因素,最后它落在了我身上,因为这样的“导出文件范围变量”,我不明白他们的行为。看看以下极其简化的机器人应用程序:
VarTestFileA.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,
}
VarTestFileB.js
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
)- 传递值而不是引用,但是我们传递 Function
然后是引用被传递是因为函数在 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
将具有切换值,但实际 bot
在文件 A 中声明的仍然是相同的,因为它没有被更改。现在将我们带到第三个陈述:
第三条语句:
bt.logBot()
,这会在文件A中打印bot
的初始值。因为它没有被改变。
所以这里真正的答案是,基于这种行为,我们可以声明,如果我们持有文件 A 中变量的引用,那么我们可以从另一个文件更改它们。但是我真的可以为此提供证据吗?出色地!是的,让我们看看下面
为了测试这个,让我们在文件 A 中创建另一个方法;
function getBot(){
return bot;
}
然后修改nextBot
如下:
function nextBot() {
BotC = !BotC
bot = BotA[BotC]
}
然后导出对这些方法的引用;
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())
输出如下:
{ token: 2 }
I: { token: 3 }
O: { token: 3 }
I: { token: 2 }
O: { token: 2 }
I: { token: 3 }
O: { token: 3 }
结果很有趣,因为现在文件 A 中的 bot
似乎按预期切换。
总而言之,问题是通过引用或值传递属性。 bot
来自您的初始代码是按值传递的,它不是一个复杂的项目,或者它没有声明为类型 Object
但包含一个简单的对象作为值。所以没有办法通过引用传递 bot
。我有待纠正,但我认为不能通过引用传递像 JavaScript 中的 Boolean
或作为值的简单对象的原始值的变量。但是函数是复杂类型,这意味着它们是 Object
,因此它们通过引用传递。
我希望你能按顺序找到它。
跟进
我想知道此类导出的文件范围变量的确切行为定义是什么。
因为我试图动态切换我的机器人但没能做到,一个一个地消除了因素,最后它落在了我身上,因为这样的“导出文件范围变量”,我不明白他们的行为。看看以下极其简化的机器人应用程序:
VarTestFileA.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,
}
VarTestFileB.js
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
)- 传递值而不是引用,但是我们传递 Function
然后是引用被传递是因为函数在 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
将具有切换值,但实际 bot
在文件 A 中声明的仍然是相同的,因为它没有被更改。现在将我们带到第三个陈述:
第三条语句:
bt.logBot()
,这会在文件A中打印bot
的初始值。因为它没有被改变。
所以这里真正的答案是,基于这种行为,我们可以声明,如果我们持有文件 A 中变量的引用,那么我们可以从另一个文件更改它们。但是我真的可以为此提供证据吗?出色地!是的,让我们看看下面
为了测试这个,让我们在文件 A 中创建另一个方法;
function getBot(){
return bot;
}
然后修改nextBot
如下:
function nextBot() {
BotC = !BotC
bot = BotA[BotC]
}
然后导出对这些方法的引用;
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())
输出如下:
{ token: 2 }
I: { token: 3 }
O: { token: 3 }
I: { token: 2 }
O: { token: 2 }
I: { token: 3 }
O: { token: 3 }
结果很有趣,因为现在文件 A 中的 bot
似乎按预期切换。
总而言之,问题是通过引用或值传递属性。 bot
来自您的初始代码是按值传递的,它不是一个复杂的项目,或者它没有声明为类型 Object
但包含一个简单的对象作为值。所以没有办法通过引用传递 bot
。我有待纠正,但我认为不能通过引用传递像 JavaScript 中的 Boolean
或作为值的简单对象的原始值的变量。但是函数是复杂类型,这意味着它们是 Object
,因此它们通过引用传递。
我希望你能按顺序找到它。