【问题标题】:Does ES6 module importing execute the code inside the imported file?ES6 模块导入是否执行导入文件中的代码?
【发布时间】:2016-09-16 11:28:30
【问题描述】:

js 文件中的代码在导入期间是否运行?如果是,那么一次还是每次? 例如

// a.js
console.log("A");
const a = "a"; 
export default a;

// b.js
import a from "./a"; // => console logs?

// c.js
import a from "./a"; // => console logs again?

【问题讨论】:

    标签: javascript ecmascript-6 es6-modules


    【解决方案1】:

    是的,确实有一次。

    http://www.ecma-international.org/ecma-262/6.0/#sec-abstract-module-records:

    如果此模块已被评估,则不执行任何操作。否则,传递评估该模块的所有模块依赖关系,然后评估该模块

    【讨论】:

    • 我只能结合 webpack 来测试它。是执行默认浏览器行为(在规范中定义)。这可以使用还是反模式? (谢谢,我更正了括号)
    • @user2520818: “如果这个模块已经被评估过,什么都不做。否则,传递地评估这个模块的所有模块依赖,然后评估这个模块。” ecma-international.org/ecma-262/6.0/…
    • 不需要 web pack 来测试这个。例如,您可以使用 babel-node 运行它。这不是反模式。这就是它的工作方式。它目前可能在你最喜欢的浏览器中工作,也可能不工作,但任何执行它的环境都会以这种方式执行它。
    • 感谢@FelixKling,无耻地窃取了您的链接。
    • “你为什么只是尝试,结果却一团糟”与“保证每次都会有这种行为,没有例外”之间存在差异;)
    【解决方案2】:

    如果有人在使用带有 "module": "es6" 的 TypeScript 并想知道如何做到这一点,请使用 globalThis 关键字:

    function outputMsg(msg: string) : void {
        console.log(msg);
    }
    
    // export function for global scope
    globalThis.outputMsg = outputMsg;
    

    然后像往常一样在 Chrome DevTools 控制台中调用 outputMsg("my console output"),它应该会自动完成并运行您的函数。

    您也可以重命名“全局导出”:

    globalThis.myCrazyFunc = outputMsg;
    

    并在控制台中调用myCrazyFunc("crazy message")

    【讨论】:

      【解决方案3】:

      接受的答案并不完全正确。

      一个模块在导入时会执行一次,但是...一个项目中可能安装了多个模块的副本,在这种情况下代码会被执行多次! p>

      考虑如果 a.jsb.jsc.js 位于三个单独的包(package_a、package_bpackage_c)和 package_bpackage_c 都指定 package_a 作为依赖项,并且您的项目指定 package_bpackage_c

      node_modules/
      ├── package_b/
      │   └── node_modules/
      │       └── package_a/
      |           └── a.js
      └── package_c/
          └── node_modules/
              └── package_a/
                  └── a.js
      

      因为 package_a 将被安装两次(就您的项目而言,这是两个完全不同的包),a.js 中的代码将被导入,因此执行两次

      很多关注这个问题的人不太可能意识到节点的这个怪癖,但如果他们关注这个问题,可能需要知道。

      这是一篇关于 understanding-the-npm-dependency-model 的旧但不错的文章,其中详细介绍了 npm 如何以及为何这样做。

      【讨论】:

      • 我认为这个答案具有误导性和错误性。给出问题标题的适用规范是 ECMAScript 6,而不是“npm 依赖模型”。特别是Module SemanticsHostResolveImportedModule。即使对于npm,链接的文章也提到了模块的副本(例如,不同的版本、不同的路径、在自己的沙箱中运行)。因此即使对于npm,相同的模块代码也不会运行两次。
      • @Inigo ES6 我认为您误解了答案,因为它是正确的,至少在撰写本文时是最新版本。至于范围,ES6 主要用于 node+npm 环境,其中接受的答案是危险的不正确,因此这是一个完全有效且有用的答案。请记住,本网站的重点是帮助彼此解决或避免问题;-)
      猜你喜欢
      • 2021-11-03
      • 2019-10-23
      • 2015-06-02
      • 2016-02-12
      • 2015-12-24
      • 2017-01-04
      • 2012-12-16
      • 1970-01-01
      相关资源
      最近更新 更多