【问题标题】:How do I avoid adding JavaScript ES6 module exports to global scope for use in normal script blocks?如何避免将 JavaScript ES6 模块导出添加到全局范围以在普通脚本块中使用?
【发布时间】: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 是目前最简单、最强大的一个。那里有关于如何启动和运行的很好的指南。

标签: javascript es6-modules


【解决方案1】:

如果您希望该函数在全局范围内可用,实现此目的的唯一方法是将其置于全局范围内(又名window 对象)。

然而,将事物放在全局范围内的更好方法是拥有某种包含所有全局变量的 globals 对象,而不是将函数/属性名称直接放在 window 对象上这可能会导致与其他第三方库发生冲突。

所以你会说globals.foo() 而不是window.foo()

【讨论】:

    【解决方案2】:

    一个函数可以通过将它重新导入到许多模块来在任何地方访问。

    您只需要将对象添加到全局范围内,其中 state 是跨模块维护和需要的。

    【讨论】:

      【解决方案3】:
      1. 创建文件 ajax.js:创建类,示例 Ajax,以导出 Ajax 结束该类。
      2. 创建一个 main.js 文件,type=module
      3. 放入 main.js:Ajax 类与 import { Ajax } from "ajax.js"
      4. 在 main.js 中创建:带有 var ajax = new Ajax(); 的新类
      5. 然后将该变量放入窗口对象中:window.ajax = ajax。
      6. 现在您已准备就绪,可以在应用程序的任何地方使用该 ajax 对象。
      7. 如果您将所有代码捆绑在类中并将它们放在同名文件中,您将拥有一个 非常模块化的应用程序,

      【讨论】:

        猜你喜欢
        • 2016-06-06
        • 1970-01-01
        • 2015-09-20
        • 1970-01-01
        • 1970-01-01
        • 2023-03-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多