We can also think of these as module specifications
. The question here is, what are the systems that Javascript uses to import and export code from various files and packages, and how are they different?
Reading
Navigating the module maze: history of JavaScript module systems
- Mentions ESM and CJS
- Asks “what is a module?”
- Talks about Revealing Module Pattern (which I had never heard of) Revealing Module Pattern
CommonJS
- Synchronous
- Doesn’t work in the browser
- Includes a Module Specification
var someModule = require('someModule')
exports = {}
AMD
- “Asynchronous Module Definition”
- Asynchronous
- Designed for a browser environment where network connection is less dependable and you may want to load multiple dependencies at once
- A competing specification for modules, usually used in the browser
RequireJS
- Probably most popular implementation of AMD
- Implements the AMD API (but wants to keep the spirit of CommonJS)
- Async
- Offers CommonJS wrappers so that CommonJS modules can be directly imported for use with RequireJS
Browserify
Allows you to ‘require’ modules in the browser by bundling up all of your dependencies.
- Open source
- Javascript bundler
- Allows devs to write Node.js-style modular code and use it in the browser
- Kind of old…? Is it still relevant?
- Supports “transforms” which are kinda cool
- Webpack and Rollup competed with it back in the day
Native ES Modules (EMS)
- Standardized into ECMAScript in 2015
- import and export
- Browser support
- Also support in Node.js
- Future proof (part of JS standard)
- Is synchronous but has an optional
import
asynchronous option!
Revealing Module Pattern
They use IIFEs (immediately invoked function expressions):
(function(){})()
Note to me: if that’s hard to remember, just note that it’s a normal function wrapped wrapped in an invoked closure: ()()
. There are at least two anatomical mnemonics that may help encode the immediacy part.
So his creates a local scope for all variables and methods. Only public methods will have access to the code inside an IIFE.
These are so cool. Here’s an example @Rahulx1 on medium.) gives:
var namesCollection = (function() {
// private members
var objects = [];
// Public Method
function addObject(object) {
objects.push(object);
printMessage(object);
}
// Private Method
function printMessage(object) {
console.log("Object successfully added:", object);
}
// public members, exposed with return statement
return {
addObject: addObject,
};
})();
Only the methods we want are returned! Wild! By the way, it’s okay to put the return statement at the top of the file. This…made no sense to me, so I investigated.
I actually tried this, and it didn’t work. But it did work if I put the return statement below this line:
var objects = []
This seems to be due to something called function hoisting
, in which the interpreter function declarations to the top of their scope before code execution. This means that you can call a function before it is declared in your code without encountering an error!
Okay definitely learning some new things here. Check this out Function Declarations vs. Function Expressions & Hoisting
Validity Qualification!
This article was written a while ago and a few of the examples here don’t actually work quite as expected, but this is probably because they are using intentionally weird syntax that probably shouldn’t work, and his been weeded out.
This actually taught me something much more important, which is the different between function declarations
and function expressions
Function declaration:
function foo(){}
Function expression:
const bar = function(){}
// or
const bar = () => {}
This gives an error:
console.log(hoist())
const hoist = () => "moose"
Cannot access ‘hoist’ before initialization. I tested this in
ts
andjs
just to be sure.
This does not:
console.log(hoist())
function hoist(){
return "hoist"
}
I was getting some mixed messages about which is called an expression
and which is called a declaration
so I called up my old friend MDN and she confirmed.
What I finally understand now is that arrow functions are a (relatively) more modern version of traditional function expressions. They’re nice because now function declarations and expressions look super different.
It turns out, declarations are loaded when the code is compiled, not when it’s executed, whereas expressions seem to be loaded and executed in the same step.