javascript - ES6 Javascript 的导出文件范围变量
问题描述
跟进What is file scope in javascript,从中我知道可能有也可能没有所谓的文件范围变量,但是,我确实记得在某处读过这样的术语,但再也找不到它了,除了问答什么是 javascript 中的文件范围。反正,
我想知道此类导出的文件范围变量的确切行为定义是什么。
因为我试图动态切换我的机器人但无法做到,一一消除因素,它最终落在了我身上,这是因为这种“导出的文件范围变量”,而我不理解它们的行为。看看以下极其简化的机器人应用程序:
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 }
另外,我尝试从 inside 切换bot
,VarTestFileA.js
它在其中工作,但从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()
这实际上更改了文件 A 中dt.bot
的值而不是 true 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 }
结果很有趣,因为现在bot
来自文件 A 的文件似乎正在按预期切换。
总之,问题是通过引用或值传递属性。bot
从您的初始代码按值传递,它不是一个复杂的项目,或者它没有声明为类型Object
,而是将一个简单的对象作为值。所以没有办法bot
通过引用传递。我有待纠正,但我不认为像Boolean
JavaScript 中的 a 那样保存原始值的变量或作为值的简单对象可以通过引用传递。但是函数是复杂类型,这意味着它们是Object
s,因此它们是通过引用传递的。
我希望你能按顺序找到这个。
推荐阅读
- ajax - 为什么我对 JAVA-servlet 的 AJAX 调用不起作用
- java - 如何生成一个以零开头并有10位数字的随机手机号码,以零开头?
- reactjs - 我无法使用主键将对象添加到领域
- java - 如何生成通过从 Arraylist 中递归删除所有奇数索引元素创建的序列,以便我们最后只得到 1 个元素?
- nginx - IdentityServer4 中的发现文档在 Ubuntu nginx 上返回 404
- ionic4 - viewdidenter 上的离子滚动顶部特定元素
- python-2.7 - 通过使用 python pandas 删除不需要的行来读取文件
- android - 如何在应用重启之间保存和恢复 Flutter ListView 的滚动位置?
- actions-on-google - 在 Google Home 设备上,下一个 MediaObject 一秒钟后停止播放
- javascript - 在同一个组件内多次集成 Ng-Survey