【发布时间】:2019-02-28 04:56:44
【问题描述】:
到目前为止,我已经设法避免了核心 JavaScript 编程,但看起来这种情况即将结束。在为一个重大的新项目做准备时,我试图了解 2018 年的最佳实践。我已经阅读了很多关于不同模块方法的文章,并使用了一些像 Dojo 的基于 AMD 的模块。在思考如何设计我自己的模块架构时,似乎 ES6 是进行新开发的正确方法。到目前为止,我了解了导入/导出语法,并且已经得到了一些简单的模块来工作。但是我目前在 HTML 中加载模块并使用它们的技术只是“感觉不对”。让我总结一下我到目前为止所做的工作。
模块 foo.js
import (bar} from '/Scripts/bar.js'
export function foo() {
bar();
console.log("I'm in foo");
}
模块 bar.js
export function bar() {
console.log("I'm in bar");
}
index.html
<head>
<script type="module">
import {foo} from "/Scripts/foo.js"
window.foo = foo; // save for later but "feels wrong"
</script>
</head>
<body>
<script>
// foo(); // doesn't work - foo by itself is only defined in the module scope
window.foo(); // unless "stashed" somewhere else
</script>
</body>
也许这是正确的技术(我找到了an older question that did basically the same as me),但我仍然不觉得我应该像这样污染全局命名空间。假设这很糟糕,我还应该做什么?
【问题讨论】:
-
如果您希望该功能在全球范围内可用,实现该功能的唯一方法是将其置于全局范围内。除非我误解了你的问题?将事物放在全局范围内的一种更好的方法是拥有某种包含所有全局变量的
globals对象,而不是将实际的函数/属性名称放在window上,这可能会导致冲突。所以你会说globals.foo()而不是window.foo() -
把它放在全局命名空间in中,就像ES6之前一样?
-
@mhodges:是的,这基本上就是问题所在。你是对的,除了
window之外,还有其他容器可以使用,比如你所说的简单属性存储或“命名空间”等。感觉模块导入应该在这个级别引入它自己的范围,而我只是缺少正确的语法(我在询问之前做了尽职调查/搜索)。但听起来这不是它的工作方式。我想我应该接受@mhodges 评论作为答案。 -
@JimHanks 如果你使用像 Webpack 这样的捆绑器/模块加载器,你绝对可以做你想做的事。每个 js 文件都将包含其导入列表,这些导入列表仅在加载该文件时才加载。您的全局范围不会受到污染,并且一切都是独立的。如果这是您想要实现的目标,我强烈建议您使用这种方法。但是,如果您不想使用捆绑程序/模块加载器,我认为使用您自己的命名空间和全局对象将是您最好的选择
-
@JimHanks 我还要补充一点(2018 年),对于中型到大型项目,使用捆绑器/模块加载器绝对是要走的路。 Webpack 是目前最简单、最强大的一个。那里有关于如何启动和运行的很好的指南。