The problem I have is that when I call onload()
, the main()
function of the script.js file should be executed, but it is not. When I delete the import ...
line, the main()
function is ready to be called, but I can’t because I want to call another function from the other JS file.
index.html:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Demo</title>
<script src="js/script.js"></script>
</head>
<body onload="main()">
<div id="allScreen">
</div>
</body>
</html>
script.js:
import { createNewScreen } from "./createScreen";
let screens = [];
function main(){
screens.push(createNewScreen());
document.getElementById('allScreen').appendChild(screens[0]);
}
createScreen.js:
export function createNewScreen(){
let screen = document.createElement('div');
screen.style.width = '500px';
screen.style.height = '300px';
screen.style.backgroundColor = 'orange';
return screen;
}
The main()
function should be called.
2
Answers
You can only use
import
inside a module.You have to load the
<script>
as a module withtype="module"
.If you had looked at the browser’s developer tools Console, you would have seen an error message when you tried to use
import
. Always use the Console when debugging your code!.Top level variables in modules are scoped to the module, they are not globals. (This is a good thing. Globals are a good way to make hard-to-maintain, fragile code.).
Intrinsic event attributes (like
onload
) depend on globals. This is one of many reasons that they are best avoided. Now we don’t have to worry about Internet Explorer 8 we can freely useaddEventListener
instead.You can use it to call
main
inside your JS file.That said, there doesn’t seem to be any reason to wait for the
load
event. Instead you can just callmain()
or move its contents to the top level of the module. Modules aren’t run immediately so the DOM will be ready by the time it triggers.There are three problems there:
import
in a non-module script, and you’re loading that file as a non-module scriptmain
wouldn’t be a global anymore because top-level declarations in modules aren’t globals, and you can only call global functions from oldonXYZ
-attribute-style event handler (one of the many reasons not to use them).import
forcreateScreen.js
. The JavaScript engine doesn’t do fancy resolution like some bunders (and Node.js) do where you can leave it off.Instead:
type="module"
on your script tag, andmain
function directly. Modules (unlike non-module scripts) aren’t executed until the HTML is loaded, so you don’t have to wait for theload
event. (You could, though, if you really want to wait for all images to be loaded and such, by usingaddEventListener
onbody
to hook up aload
handler. You’d want to checkdocument.visibilityState
to see whether it had already fired. But in general, best not to wait that long.)import
:Here’s an example of #1 and #2 (can’t do a separate module with file name using Stack Snippets, unfortunately):
Notice how
main
is able to get the element, even though it’s defined after the script. That’s because of the way modules are auto-deferred.