MODULES

We can export values out of a module, simple values or even entire functions.
Whatever we export from a module is called the public API.
This public API is actually consumed by importing values into a module.
These other modules from which we import are then called dependencies of the importing module.

The differences between old school scripts and modern ES6 modules is that, in MODULES, all top level variables are scoped to the module. So variables are private to the module by default and the only way an outside module can access a value that's inside of a module is by exporting that value. So if we don't export the variables from the module, then no outside modules can use those variable.
In SCRIPTS, on the other hand, all top level variables are always global and this can lead to problems like global namespace pollution, where multiple scripts try to declare variables with the same name and then these variables collide.

ES6 MODULES are always executed in strict mode while SCRIPTS on the other hand are executed in sloppy mode by default. So with modules, there is no more need to manually declare strict mode.

In MODULES the "this" keyword is always undefined at the top level while in SCRIPTS it points at the window object.

With MODULES, we can export and import values between them using this ES6 import and experts syntax. In regular SCRIPTS, importing and exporting values is just completely impossible.

Imports and exports can only happen at the top level, i.e., outside of any function or any if block.

All Imports are Hoisted.

The code of the importing modules gets executed first, then the code of the actual module, that we are in, gets executed.

In order to link a module to an HTML file, we need to use the script tag with the type attribute set to module, instead of just a plain script tag.

HOW MODULES ARE IMPORTED

Whenever a piece of code is executed, the first step is to parse that code.
Parsing basically means to just read the code, without executing it.
In this moment, the imports are hoisted.

The connection imported and exported value is a live connection, what that means is exported values are not copied to imports. Instead, the imported value is basically just a reference to the exported values like a pointer. So when the value changes in the exporting module, then the same value also changes in the importing module.

In ES6 modules, there are two types of exports, Named Exports and Default Exports.

In NAMED EXPORT,
All we have to do is to put export in front of anything, that we want to export.
While importing, we have to use the exact same name of the variable that we are importing and put it inside of curly braces.
We can export multiple variables from one module.
We can also change the name of variables while importing/exporting them using the "as" keyword.

Example of NAMED EXPORT

In DEFAULT EXPORT,
usually, we use, only when we want to export one thing per module, that's the reason why they are called default.
We can mix default and named imports, but we should never do it.
We just export the function or variable we want to, without naming it, from the exporting module and call it whatever we want in the importing module.

Example of DEFAULT EXPORT