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 onlymain.js
which internally is importingbase.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
4 Answers
Reset to default 7One 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>