Learn JavaScript in Construct, part 12: Modules

15

Index

Attached Files

The following files have been attached to this tutorial:

.c3p

modules-template.c3p

Download now 47.07 KB
.c3p

imports-for-events.c3p

Download now 47.58 KB

Stats

5,884 visits, 14,705 views

Tools

Translations

This tutorial hasn't been translated.

License

This tutorial is licensed under CC BY-NC 4.0. Please refer to the license text if you wish to reuse, share or remix the content contained within this tutorial.

Import and export

Here's a few more things you can do with the import and export keywords. This isn't comprehensive, but is a useful summary.

Import specific function

Re-using our previous example, the GetMessage() function can also be imported and used like this:

import { GetMessage } from "./mymodule.js";

console.log(GetMessage());

In this example, import { GetMessage } from "./mymodule.js"; means to import only the GetMessage function exported from mymodule.js. It also is made a top-level function, so is called with just GetMessage() alone; there is no object named MyModule.

Multiple things can be imported with the form: import { FuncA, FuncB, FuncC } from "./file.js";

The original example imported everything and gave it a name. This approach is useful if you know you only need to import some specific things and you don't need absolutely everything.

Import script just to run it

You can also use import "./file.js"; to just load and run a script file. It won't import anything or use its exports in any way.

This can be useful for older libraries which don't export anything and instead just add global variables. In this case after importing the script you can access anything it added to globalThis. Alternatively it's possible the script does something useful just by running its top-level code, in which case you don't need to import anything, as merely loading and running the script is sufficient.

Default export

If a script only has a single export, or has a main thing that you'll want to import most of the time, that can be made a default export. This means it is exported with export default instead of just export. Try the code below for mymodule.js.

export default function GetMessage()
{
	return "Hello world from mymodule.js!";
}

Default exports are in turn imported slightly differently. Try the code below for main.js.

import GetMessage from "./mymodule.js";

console.log(GetMessage());

Now preview the project and the message will be logged.

In this case import Thing from "./file.js" means to import the default export from file.js and give it the name Thing. Note this doesn't use the braces { and } in the previous example (which imported exports with specific names), or the * or as parts (which import everything).

Don't forget that a script imported this way must specify a default export, otherwise you'll get an error.

Imports are read-only

Everything you import is read-only, as in it cannot be re-assigned. This helps ensure modules always expose a consistent interface.

However sometimes this can pose a bit of a problem. For example if you want to export a variable like this:

export let myVariable = 2;

And import it like this:

import { myVariable } from "./mymodule.js";

// TypeError: Assignment to constant variable.
myVariable = 3;

...then after the import, you cannot change the value of myVariable. Even though we exported the variable declared with let, it still acts as if it's really const.

One way around this problem is to use an object. The object itself cannot be reassigned, but its properties can. Therefore we can use object properties instead of variables. Here's an example showing how this can be used as a way to store groups of related variables in a module. In mymodule.js use:

export default {
	score: 100,
	lives: 3,
	ammo: 50
};

This uses a default export of an object with properties for score, lives and ammo.

Then in main.js use:

import GameVariables from "./mymodule.js";

GameVariables.score += 100;

console.log(`Score: ${GameVariables.score}`);

This imports the default export with the name GameVariables. That object is itself not re-assignable, but it doesn't matter: its properties can be changed, so the line GameVariables.score += 100 works as expected, resulting in a total score of 200.

This is a useful technique for managing sets of related variables as their own modules. For example you could use this for "global" variables - which wouldn't actually be in global scope (as they're not actually on the global object), but provides a better organised way to share a set of variables across all your code.

What can be exported

You can export pretty much anything from a script file. However since anything that is imported is read-only (i.e. not re-assignable), it's not very useful to export variables, as they will always work as if they were declared with const. Usually modules export objects, functions and classes, as these are the most useful things to share.

Next Tutorial In Course

Learn JavaScript in Construct, part 13: Onwards 17:33

Learn where to go next, with lots more resources to explore, some final bits of advice, and closing remarks.

  • 1 Comments

  • Order by
Want to leave a comment? Login or Register an account!
  • This clears so many confusions, still hope to see more tutorials on how to use the javascript and even sheet together.