Tern Systems,以下是对Stack Overflow问题的深思熟虑的回答:
简短回答
在现代JavaScript模块中(
<script type="module">
),变量的作用域为模块本身
不
自动附着到全局对象(
window
). 因此,非模块脚本中的代码不能直接访问模块脚本中导入或声明的变量。如果你想与非模块脚本共享它们,你需要从模块中显式导出它们,或者将它们附加到全局对象。
详细说明
-
模块范围隔离
当你使用
<脚本类型=“模块”>
,在该脚本中声明的任何变量、类或函数都是模块范围的。他们确实如此
不
以正态变量的方式泄漏到全局范围
<script>
这种设计可以防止意外的碰撞,并促进更好的封装。
-
为什么不能在非模块中访问模块变量
-
非模块脚本(或控制台,如果您直接从浏览器DevTools控制台进行测试)在
窗口
对象,默认情况下只包含在全局范围内声明的变量。
-
如果您的脚本是一个模块,则除非明确导出,否则其中声明的任何内容都将保留在模块本地范围内。
-
如何从模块中暴露变量
如果你想让非模块脚本(或全局作用域)看到你的模块变量:
-
附至
窗口
对象
// Inside your module:
const myValue = 42;
window.myValue = myValue;
现在,非模块脚本(甚至HTML中的内联代码)可以做到:
console.log(window.myValue); // 42
-
进出口机制
(用于模块间通信)
如果两个脚本都是模块,则可以从一个模块导出并导入另一个模块:
// moduleA.js
export const myValue = 42;
<!-- moduleB -->
<script type="module">
import { myValue } from './moduleA.js';
console.log(myValue); // 42
</script>
-
确保脚本类型一致
-
如果您将模块脚本和非模块脚本混合使用,请注意,在一个作用域中声明的变量在另一个范围中不会自动可用。
-
对于某些项目,将所有脚本保持为模块以实现一致的导入/导出模式更简单。
实用建议
-
将依赖脚本转换为模块
只要有可能,转换所有
<脚本>
标签到
type="module">
。这样,您可以使用Javascript本机模块系统,使用
export
和
import
正如预期的那样。
-
仅在必要时使用全局对象
如果您真的需要全局访问,以便快速验证概念,请访问
窗口
这是一种简单的方法。然而,从设计的角度来看,全局变量可能会导致命名冲突和维护问题。明智地使用它们。
-
检查浏览器支持
大多数现代浏览器完全支持
<脚本类型=“模块”>
,但您可能需要对旧环境进行转换或使用polyfills。如果你针对的是传统浏览器,请记住这一点。
模块脚本旨在提供更健壮和封装的代码结构。如果需要与非模块脚本共享变量,请将它们显式分配给全局范围,或者重构代码以仅使用模块。通过遵循导入/导出标准,您将维护更清晰、更可维护的代码。