我正在使用ES6
Chrome v65
功能
我有以下文件:
base.js :
export function consoleLogger(message) {
console.log(message);
}
main.js
import { consoleLogger } from './base.js';
consoleLogger('Some message');
utils.js
function sayMyName(name) {
console.log(name);
}
imports.html
<!DOCTYPE html>
<html>
<head>
<script src='./main.js' type='module'></script>
<script src='./utils.js'></script>
</head>
<body>
<script>
sayMyName('Cool name');
</script>
</body>
</html>
像这样使用一切似乎都很好,在控制台我得到了
酷名称utils.js:2
一些消息base.js:2
但是,让我们想象一下,我需要一些额外的数据来构建consoleLogger
方法的消息。然后我想在 main.js
function logToConsole(msg) {
consoleLogger(msg);
}
并在 imports.html
中<script>
sayMyName('Cool name');
logToConsole('Send from log to console');
</script>
然后我在控制台的logToConsole('Send from log to console');
文件中调用了html
:
未捕获的ReferenceError:未定义logToConsole 在imports.html:10
因此从consoleLogger
导入base.js
并直接在main.js
中调用它是没有问题的,包含另一个.js文件(utils.js
)没有问题并从那里调用方法,但如果我尝试调用在main.js
中声明的方法,内部调用导入的方法,我从上面得到了错误。因为似乎来自main.js
的方法是否引用了导入的方法并不重要。我刚评论了所有内容,只留下了一个简单的方法
main.js
import { consoleLogger } from './base.js';
/*function logToConsole(msg) {
consoleLogger(msg);
}
consoleLogger('Some message');*/
function randomStuff() {
console.log('random stuff');
}
在控制台中我收到了这个错误:
imports.html:11未捕获的ReferenceError:未定义randomStuff 在imports.html:11
有人可以解释一下这种行为的原因吗?
答案 0 :(得分:2)
ES模块(以及一般的JS模块)的目的之一是防止全球范围内的污染。
模块导出不应泄漏到全局范围。模块的使用通常假定所有第一方代码都驻留在模块中。 logToConsole('Send from log to console')
转到主模块。
如果需要与全局范围进行互操作,则应将变量显式公开为模块中的全局变量:
window.logToConsole = function (msg) {
consoleLogger(msg);
}
正如另一个答案所提到的,仍然可能存在竞争条件,因为模块是异步加载的。应该推迟脚本,直到文档准备就绪 - jQuery ready
事件或本机对应物:
<script>
document.addEventListener('DOMContentLoaded', () => {
logToConsole('Send from log to console');
});
<script>
答案 1 :(得分:1)
这是因为这一行 -
<script src='./main.js' type='module'></script>
带有type="module"
的脚本会延迟执行,直到满足其依赖关系。与此同时。其他脚本只会执行。
这意味着你的
<script>
sayMyName('Cool name');
logToConsole('Send from log to console');
</script>
将在&#39;模块脚本之前执行&#39; main.js已得到解决和评估。
答案 2 :(得分:1)
浏览器将logToConsole
中的imports.html
解释为window.logToConsole
,即它希望该函数存在于全局命名空间中。
默认情况下,es6模块中的对象在添加到HTML页面时不会放在全局命名空间中。
您可以通过在HTML中明确导入来访问logToConsole
:
<script type="module">
import { logToConsole } from './main.js';
sayMyName('Cool name');
logToConsole('Got it');
</script>
答案 3 :(得分:0)
你应该像这样导出main.js中的函数:
export function logToConsole(msg) {
然后您可以使用
导入它 带有导入内容的 <script type="module">
内联脚本
请参阅https://jakearchibald.com/2017/es-modules-in-browsers/
看起来像这样:
<script type="module">
import { logToConsole } from "./main.js";
sayMyName('Cool name');
logToConsole('Send from log to console');
</script>
&#13;