DEV Community

loading...
Cover image for πŸš€ES6 MODULES 101 #1πŸš€

πŸš€ES6 MODULES 101 #1πŸš€

michalpzarzycki profile image Michal Zarzycki ・3 min read

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 };
Enter fullscreen mode Exit fullscreen mode

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'
Enter fullscreen mode Exit fullscreen mode

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!"
Enter fullscreen mode Exit fullscreen mode

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 '...'
Enter fullscreen mode Exit fullscreen mode

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 }
Enter fullscreen mode Exit fullscreen mode

To import the default value you can get rid of {}:

import helloWorld from '...'
Enter fullscreen mode Exit fullscreen mode

Unless you want to rename it:

import {default as helloWorld} from '...'
Enter fullscreen mode Exit fullscreen mode

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";
Enter fullscreen mode Exit fullscreen mode

End of part one.

πŸš€Thanks for reading!πŸš€

Discussion (1)

Collapse
micronaut profile image
Eric Danowski

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!

Forem Open with the Forem app