102

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?
4

3 回答 3

92

是的,确实有一次。

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

如果该模块已被评估,则什么也不做。否则,传递评估该模块的所有模块依赖关系,然后评估该模块

于 2016-05-19T14:06:14.697 回答
16

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

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

考虑如果a.jsb.jsc.js位于三个单独的包(分别为package_apackage_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中的代码将被导入,因此执行两次

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

这是一篇关于理解 npm-dependency-model的旧但很好的文章,其中详细介绍了 npm 如何以及为什么这样做。

于 2020-10-15T02:20:29.693 回答
1

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

function outputMsg(msg: string) : void {
    console.log(msg);
}

// export function for global scope
globalThis.outputMsg = outputMsg;

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

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

globalThis.myCrazyFunc = outputMsg;

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

于 2020-04-06T11:33:40.667 回答