skip to Main Content

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


  1. You can only use import inside a module.

    You have to load the <script> as a module with type="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 use addEventListener 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 call main() 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.

    Login or Signup to reply.
  2. There are three problems there:

    1. Your script won’t be loaded at all, because you can’t use import in a non-module script, and you’re loading that file as a non-module script
    2. If you did load it as a module script, main wouldn’t be a global anymore because top-level declarations in modules aren’t globals, and you can only call global functions from old onXYZ-attribute-style event handler (one of the many reasons not to use them).
    3. Unless you have a bundling step you didn’t mention, you need to include the file extension on your import for createScreen.js. The JavaScript engine doesn’t do fancy resolution like some bunders (and Node.js) do where you can leave it off.

    Instead:

    1. Use type="module" on your script tag, and
    2. Run your main function directly. Modules (unlike non-module scripts) aren’t executed until the HTML is loaded, so you don’t have to wait for the load event. (You could, though, if you really want to wait for all images to be loaded and such, by using addEventListener on body to hook up a load handler. You’d want to check document.visibilityState to see whether it had already fired. But in general, best not to wait that long.)
    3. Include the extension in the module specifier in the import:
      import { createNewScreen } from "./createScreen.js";
      // −−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−−^^^
      

    Here’s an example of #1 and #2 (can’t do a separate module with file name using Stack Snippets, unfortunately):

    <script type="module">
    main();
    function main(){
        const standIn = document.createElement("div");
        standIn.textContent = "Added by main";
        document.getElementById("allScreen").appendChild(standIn);
    }
    </script>
    <div id="allScreen">
    </div>

    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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search