最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Accessing exported functions from html file - Stack Overflow

programmeradmin3浏览0评论

I'm playing around with some ES6 features using Chrome v65

I have the following files:

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>

Used like this everything seems fine, and in the console I get

Cool name utils.js:2

Some message base.js:2

However lets imagine scenario where I need some additional data in order to pose the message for the consoleLogger method. Then I would like to have something like this in main.js

function logToConsole(msg) {
    consoleLogger(msg);
}

and in imports.html

<script>
    sayMyName('Cool name');
    logToConsole('Send from log to console');
</script>

then for the logToConsole('Send from log to console'); call in my html file in the console I get:

Uncaught ReferenceError: logToConsole is not defined at imports.html:10

So there is no problem to import the consoleLogger from base.js and call it directly in main.js, there is no problem to include another .js file (utils.js) and call methods from there, but if I try to call a method declared in main.js which internally calls an imported method I got the error from above. As it seems it doesn't even matter if the method from main.js is referencing an imported method or not. I just mented everything and left only one simple method

main.js

import { consoleLogger } from './base.js';

/*function logToConsole(msg) {
    consoleLogger(msg);
}

consoleLogger('Some message');*/

function randomStuff() {
    console.log('random stuff');
}

and in the console I got this error:

imports.html:11 Uncaught ReferenceError: randomStuff is not defined at imports.html:11

Can someone explain me the reason for this behavior?

I'm playing around with some ES6 features using Chrome v65

I have the following files:

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>

Used like this everything seems fine, and in the console I get

Cool name utils.js:2

Some message base.js:2

However lets imagine scenario where I need some additional data in order to pose the message for the consoleLogger method. Then I would like to have something like this in main.js

function logToConsole(msg) {
    consoleLogger(msg);
}

and in imports.html

<script>
    sayMyName('Cool name');
    logToConsole('Send from log to console');
</script>

then for the logToConsole('Send from log to console'); call in my html file in the console I get:

Uncaught ReferenceError: logToConsole is not defined at imports.html:10

So there is no problem to import the consoleLogger from base.js and call it directly in main.js, there is no problem to include another .js file (utils.js) and call methods from there, but if I try to call a method declared in main.js which internally calls an imported method I got the error from above. As it seems it doesn't even matter if the method from main.js is referencing an imported method or not. I just mented everything and left only one simple method

main.js

import { consoleLogger } from './base.js';

/*function logToConsole(msg) {
    consoleLogger(msg);
}

consoleLogger('Some message');*/

function randomStuff() {
    console.log('random stuff');
}

and in the console I got this error:

imports.html:11 Uncaught ReferenceError: randomStuff is not defined at imports.html:11

Can someone explain me the reason for this behavior?

Share Improve this question asked May 4, 2018 at 13:33 LeronLeron 9,87640 gold badges166 silver badges265 bronze badges 3
  • Since the document is parsed top-bottom (and JS is executed directly by default), maybe the problem is the order your files are included. – Seblor Commented May 4, 2018 at 13:36
  • @Seblor It seems unlikely for me since the reference tree is Imports.html -> main.js -> base.js. In the html file I include only main.js which internally is importing base.js I don't know if it's possible to change this order. – Leron Commented May 4, 2018 at 13:39
  • See also How to call one function defined in a javascript to another javascript file? and ES6 Modules: Undefined onclick function after import or Use functions defined in ES6 module directly in html – Bergi Commented May 26, 2021 at 18:30
Add a ment  | 

4 Answers 4

Reset to default 7

One of the purposes of ES modules (and JS modules in general) is to prevent the pollution of global scope.

Module exports aren't supposed to leak to global scope. The use of modules usually assumes that all first-party code resides in modules. logToConsole('Send from log to console') goes to main module.

In case there's a need to interoperate with global scope, a variable should be explicitly exposed as a global inside a module:

window.logToConsole = function (msg) {
    consoleLogger(msg);
}

As another answer already mentions, there still may be race condition because modules are loaded asynchronously. Script should be postponed until the document will be ready - jQuery ready event or native counterpart:

<script>
document.addEventListener('DOMContentLoaded', () => {
    logToConsole('Send from log to console');
});
<script>

The browser interprets logToConsole in imports.html as window.logToConsole, i.e. it expects that function to exist in the global namespace.

By default, objects in an es6 module are not placed in the global namespace when added to an HTML page.

You can access logToConsole by importing it explicitly in HTML:

<script type="module">
    import { logToConsole } from './main.js';

    sayMyName('Cool name');
    logToConsole('Got it');
</script>

That's because of this line -

<script src='./main.js' type='module'></script>

scripts with type="module" defer execution till their dependencies are met. And in the meanwhile. Other scripts will just execute.

Which means that your

<script>
    sayMyName('Cool name');
    logToConsole('Send from log to console');
</script>

will execute before the 'module script' main.js is resolved and evaluated.

you should export the function in main.js like this:

export function logToConsole(msg) {

and then you can import it using a

<script type="module"> inline script with an import inside

see https://jakearchibald./2017/es-modules-in-browsers/

would look like this:

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

发布评论

评论列表(0)

  1. 暂无评论