8

I'm writing JavaScript for the browser, my script.js has something like

import { foo, bar } from "./lib/sth.js"
function main() { ... }

Then I have this in my browser:

<script type=module src="./script.js"></script>
<body onload="main();"> ... </body>

But it's keep giving me this error:

Uncaught ReferenceError: main is not defined at onload ((index):7)

Why is my main now defined? It works fine before I use type=module, but with the import statement, I believe it has to be type=module

Dmitrii2333
  • 323
  • 1
  • 5
  • 7
  • If I am not mistaken, import is not supported natively by browsers. Do you use any compiler to compile your es6 code to plain-old js so that browser can understand it? I think that your whole script.js is not properly loaded because of that. It is not just the main() function. Do you see any other errot before that? – Alkis Mavridis Oct 12 '18 at 18:24
  • @AlkisMavridis Sure it is: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/import – Heretic Monkey Oct 12 '18 at 18:25
  • 1
    it doesn't look like script.js is a module – dandavis Oct 12 '18 at 18:25
  • 3
    Module scope != global scope. If you want `main` to be globally available, you need to do this yourself: `window.main = main;`. – Felix Kling Oct 12 '18 at 18:26
  • I think you need to enclose modulel in quotes like this `type="module"`. Also export the function in the file. Eg: `export function main(){}` – dRoyson Oct 12 '18 at 18:27
  • You probably shouldn't mix modules with global variables and inline event handler attachment. I would suggest adding something like `window.onload = function () { document.body.onload = main; }`. – Heretic Monkey Oct 12 '18 at 18:28
  • 2
    @Royson: Quotes around attribute values are optional in HTML, if the value consists only specific "safe" characters. – Felix Kling Oct 12 '18 at 18:29
  • Same confusion in my mind : it's weird that the HTML page that loads the module isn't even aware about functions defined in it ! But the module knows about the HTML page ! Intuitively, that's a complete nonsense...Well, I did like Felix said in his first post and that works. I tried to use "export" before functions but this doesn't work. – bendeg Jun 06 '22 at 11:15

1 Answers1

5

Thanks for @HereticMonkey and @FelixKling!

window.onload = function() { ... } 

does work for my problem. Yet I'm confused why import is designed like this. Suppose I just wanna use some library in my script so I import it, why this makes my script has to be a module as well?

Dmitrii2333
  • 323
  • 1
  • 5
  • 7
  • `why this makes my script has to be a module as well?` well, because you wrote ` – Patrick Roberts Oct 12 '18 at 18:48
  • 1
    @PatrickRoberts but if I use import statement without use type=module will cause an syntax error in the browser – Dmitrii2333 Oct 12 '18 at 18:55
  • Yes I'm aware, but `import` can only be used in a module scope. That's the whole point. – Patrick Roberts Oct 12 '18 at 18:56
  • 1
    That's the part I'm confused, if I use a metaphor in C/C++, I would say module is like ".h", and my scripts is just a regular ".c" file, it does make sense to me if I'm using a ".h" then my own file must be ".h" as well – Dmitrii2333 Oct 12 '18 at 19:22
  • Your metaphor doesn't make sense either. A `.h` file is a declaration, while a `.c` is an implementation. It's generally bad practice to declare things in JavaScript without defining them in the same scope. Doing so is what leads to things like [callback hell](http://callbackhell.com/) and questions that get closed as a duplicate of [this](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call/14220323) or [this](https://stackoverflow.com/questions/23667086/why-is-my-variable-unaltered-after-i-modify-it-inside-of-a-function-asynchron). – Patrick Roberts Oct 12 '18 at 20:13