从html文件

时间:2018-05-04 13:33:46

标签: javascript import ecmascript-6

我正在使用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

有人可以解释一下这种行为的原因吗?

4 个答案:

答案 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/

看起来像这样:

&#13;
&#13;
<script type="module">
    import { logToConsole } from "./main.js";
    sayMyName('Cool name');
    logToConsole('Send from log to console');
</script>
&#13;
&#13;
&#13;