A GLOBAL PROBLEM
Each of us, at the initial stage of writing scripts in JS, came to the conclusion that having all the code in one file is probably not a good solution. I remember my first attempts to divide my main javascript file into several smaller ones, trying to follow the rule that each such file should correspond to one functionality. Even though it required me to add more <script>
tags to the html file, the compensation in the form of seemingly clearer code was quite a reward. Except that not entirely.
One of the biggest problems with the pre-modular era was that code, although separated by different files, still operated at the same global scope. This caused a lot of problems, especially when two different functions in two different files have the same name. The code divide concept was good but not fine-tuned until modules.
Solution to the problem of pre-module-age global variables was to write code inside IIFE.
MODULE vs. SCRIPT
The module is a JS code in which the variables created at the highest level are not shared in the global scope, which solves our main problem in code sharing. In addition, the modules work in strict mode, which is an additional security. You also need to remember about this
, because it has a value of undefined
in the module.
Anything that does not support the above functionalities can be called a script. However, these are only superficial differences, as modules and scripts also differ in the way JavaScript is loaded and executed, but more on that later.
IMPORT / EXPORT
To export code fragments from the module, just put export
before the name of the function, variable or class:
//You can export variables
export const VARIABLE = "HELLO WORLD!";
//function export
export function fullName(name, surname) {
return name + ' ' + surname;
}
//class
export class Car {
constructor(name) {
this.name = name;
}
makeItDope() {
return `${this.name} is dope!`
}
}
//if you dont add export, this will be private in module
function iAmNotExportes() {
return "Private message"
}
//you can also export function later
function noRushDude() {
return "No worries"
}
export { noRushDude };
Once we have the module with exported items, we can import them to our file using the import {} from ""
syntax:
import { Car, fullName, VARIABLE, noRushDude } from './previousFile.js'
The from
keyword indicates the module that contains the items being exported. The name of the module is given in the form of a text string, in browsers it is given in a similar form as in the element <script src="">
(this means specifying the extension of the .js
file), however, if you import the module on the Node.js
platform, you must know that there is a distinction between local files and packages, which slightly changes the form of the path (e.g. "express"
- package name, "./express.js"
- local file).
Another interesting feature of import is that you can import the entire module. Let's have a look:
//all exported items are available inside previousFile
import * as previousFile from './previousFile.js'
console.log(previousFile.VARIABLE) //"Hello World!"
You can also rename items during import and export:
function goodCar() {
return 'BMW'
}
export {goodCar as badCar}
//==========================
//now you can import
import { badCar } from '...'
//but also rename it again!
import { badCar as goodCar } from '...'
You can also import
and export
the default values. The default value is a single variable, function or class, specified with the default
keyword. Only one default exported item can be defined:
//You can do it like this:
export default function helloWorld() {
return "Hello World!"
}
//-----------------------------------
//...or like this:
function helloWorld() {
return "Hello World!"
}
export default helloWorld
//-----------------------------------
//...or like this:
function helloWorld() {
return "Hello World!"
}
export { helloWorld as default }
To import the default value you can get rid of {}
:
import helloWorld from '...'
Unless you want to rename it:
import {default as helloWorld} from '...'
Some modules do not export anything but exist to modify global objects. Although modules do not have access to the global scope, they have access to objects such as Array, Object, Map, thanks to which they can modify them and such code can be imported. An example syntax for such an import looks like this:
import "./someModule.js";
End of part one.
πThanks for reading!π
Top comments (1)
We currently use IIFEs but I am trying to move to ES6 modules. The problem I am running into is for testing, how do you mock/spy/stub a module that the module under test is importing? We use Jasmine with Karma. I've tried a couple of babel plugins to rewire the modules to allow spying/stubbing but I'm wondering what other people are using? Thanks!