> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/getify/You-Dont-Know-JS/llms.txt
> Use this file to discover all available pages before exploring further.

# Chapter 8: The Module Pattern

> Learn how modules embody scope and closure, explore classic modules, Node CommonJS, and modern ES Modules (ESM) to organize your JavaScript programs.

In this chapter, we wrap up the main text of the book by exploring one of the most important code organization patterns in all of programming: the module.

As we'll see, modules are inherently built from what we've already covered: the payoff for your efforts in learning lexical scope and closure.

<Note>
  The central theme of this book has been that understanding and mastering scope and closure is key in properly structuring and organizing our code, especially the decisions on where to store information in variables.
</Note>

## Encapsulation and Least Exposure (POLE)

Encapsulation is often cited as a principle of object-oriented (OO) programming, but it's more fundamental and broadly applicable than that.

The goal of encapsulation is the bundling or co-location of information (data) and behavior (functions) that together serve a common purpose.

### What Makes Encapsulation

Independent of any syntax or code mechanisms, the spirit of encapsulation can be realized in something as simple as using separate files to hold bits of the overall program with common purpose.

Another key goal is the control of visibility of certain aspects of the encapsulated data and functionality. In JS, we most often implement visibility control through the mechanics of lexical scope.

<Tip>
  The idea is to group alike program bits together, and selectively limit programmatic access to the parts we consider *private* details. What's not considered *private* is then marked as *public*, accessible to the whole program.
</Tip>

The natural effect of this effort is better code organization. It's easier to build and maintain software when we know where things are, with clear and obvious boundaries and connection points.

## What Is a Module?

A module is a collection of related data and functions (often referred to as methods in this context), characterized by a division between hidden *private* details and *public* accessible details, usually called the "public API."

A module is also stateful: it maintains some information over time, along with functionality to access and update that information.

### Namespaces (Stateless Grouping)

If you group a set of related functions together, without data, then you don't really have the expected encapsulation a module implies. The better term for this grouping of *stateless* functions is a **namespace**:

```javascript theme={null}
// namespace, not module
var Utils = {
    cancelEvt(evt) {
        evt.preventDefault();
        evt.stopPropagation();
        evt.stopImmediatePropagation();
    },
    wait(ms) {
        return new Promise(function c(res){
            setTimeout(res,ms);
        });
    },
    isValidEmail(email) {
        return /[^@]+@[^@.]+\.[^@.]+/.test(email);
    }
};
```

`Utils` here is a useful collection of utilities, yet they're all state-independent functions. Gathering functionality together is generally good practice, but that doesn't make this a module. Rather, we've defined a `Utils` namespace.

### Data Structures (Stateful Grouping)

Even if you bundle data and stateful functions together, if you're not limiting the visibility of any of it, then you're stopping short of the POLE aspect of encapsulation:

```javascript theme={null}
// data structure, not module
var Student = {
    records: [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ],
    getName(studentID) {
        var student = this.records.find(
            student => student.id == studentID
        );
        return student.name;
    }
};

Student.getName(73);
// Suzy
```

Since `records` is publicly accessible data, not hidden behind a public API, `Student` here isn't really a module. It's best to label this an instance of a data structure.

### Modules (Stateful Access Control)

To embody the full spirit of the module pattern, we not only need grouping and state, but also access control through visibility (private vs. public).

Let's turn `Student` into a module. We'll start with a form called the "classic module":

```javascript theme={null}
var Student = (function defineStudent(){
    var records = [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ];

    var publicAPI = {
        getName
    };

    return publicAPI;

    // ************************

    function getName(studentID) {
        var student = records.find(
            student => student.id == studentID
        );
        return student.name;
    }
})();

Student.getName(73);   // Suzy
```

`Student` is now an instance of a module. It features a public API with a single method: `getName(..)`. This method is able to access the private hidden `records` data.

<Note>
  The instance of the module is created by the `defineStudent()` IIFE being executed. This IIFE returns an object (named `publicAPI`) that has a property on it referencing the inner `getName(..)` function.

  From the outside, `Student.getName(..)` invokes this exposed inner function, which maintains access to the inner `records` variable via closure.
</Note>

#### Classic Module Definition

So to clarify what makes something a classic module:

<Steps>
  1. There must be an outer scope, typically from a module factory function running at least once.

  2. The module's inner scope must have at least one piece of hidden information that represents state for the module.

  3. The module must return on its public API a reference to at least one function that has closure over the hidden module state.
</Steps>

#### Module Factory (Multiple Instances)

If we want to define a module that supports multiple instances, we can slightly tweak the code:

```javascript theme={null}
// factory function, not singleton IIFE
function defineStudent() {
    var records = [
        { id: 14, name: "Kyle", grade: 86 },
        { id: 73, name: "Suzy", grade: 87 },
        { id: 112, name: "Frank", grade: 75 },
        { id: 6, name: "Sarah", grade: 91 }
    ];

    var publicAPI = {
        getName
    };

    return publicAPI;

    // ************************

    function getName(studentID) {
        var student = records.find(
            student => student.id == studentID
        );
        return student.name;
    }
}

var fullTime = defineStudent();
fullTime.getName(73);            // Suzy
```

Rather than specifying `defineStudent()` as an IIFE, we just define it as a normal standalone function, commonly referred to as a "module factory" function.

## Node CommonJS Modules

Unlike the classic module format, where you could bundle the module factory or IIFE alongside any other code, CommonJS modules are file-based; one module per file.

Let's tweak our module example to adhere to that format:

```javascript theme={null}
module.exports.getName = getName;

// ************************

var records = [
    { id: 14, name: "Kyle", grade: 86 },
    { id: 73, name: "Suzy", grade: 87 },
    { id: 112, name: "Frank", grade: 75 },
    { id: 6, name: "Sarah", grade: 91 }
];

function getName(studentID) {
    var student = records.find(
        student => student.id == studentID
    );
    return student.name;
}
```

The `records` and `getName` identifiers are in the top-level scope of this module, but that's not the global scope. Everything here is *by default* private to the module.

To expose something on the public API of a CommonJS module, you add a property to the empty object provided as `module.exports`.

<Tip>
  For style purposes, I like to put my "exports" at the top and my module implementation at the bottom. But these exports can be placed anywhere.
</Tip>

Some developers have the habit of replacing the default exports object. As such, I recommend against replacing the object. If you want to assign multiple exports at once, you can do this:

```javascript theme={null}
Object.assign(module.exports,{
   // .. exports ..
});
```

To include another module instance into your module/program, use Node's `require(..)` method:

```javascript theme={null}
var Student = require("/path/to/student.js");

Student.getName(73);
// Suzy
```

`Student` now references the public API of our example module.

<Note>
  CommonJS modules behave as singleton instances, similar to the IIFE module definition style. No matter how many times you `require(..)` the same module, you just get additional references to the single shared module instance.
</Note>

`require(..)` is an all-or-nothing mechanism. To effectively access only part of the API:

```javascript theme={null}
var getName = require("/path/to/student.js").getName;

// or alternately:
var { getName } = require("/path/to/student.js");
```

## Modern ES Modules (ESM)

The ESM format shares several similarities with the CommonJS format. ESM is file-based, and module instances are singletons, with everything private *by default*.

One notable difference is that ESM files are assumed to be strict-mode, without needing a `"use strict"` pragma at the top.

Instead of `module.exports` in CommonJS, ESM uses an `export` keyword to expose something on the public API of the module. The `import` keyword replaces the `require(..)` statement:

```javascript theme={null}
export { getName };

// ************************

var records = [
    { id: 14, name: "Kyle", grade: 86 },
    { id: 73, name: "Suzy", grade: 87 },
    { id: 112, name: "Frank", grade: 75 },
    { id: 6, name: "Sarah", grade: 91 }
];

function getName(studentID) {
    var student = records.find(
        student => student.id == studentID
    );
    return student.name;
}
```

The only change here is the `export { getName }` statement. `export` statements can appear anywhere throughout the file, though `export` must be at the top-level scope.

### ESM Export Variations

ESM offers variation on how the `export` statements can be specified:

```javascript theme={null}
export function getName(studentID) {
    // ..
}
```

Even though `export` appears before the `function` keyword here, this is still a `function` declaration that also happens to be exported. The `getName` identifier is *function hoisted*, so it's available throughout the whole scope of the module.

Another allowed variation:

```javascript theme={null}
export default function getName(studentID) {
    // ..
}
```

This is a "default export," which has different semantics from other exports. Non-`default` exports are referred to as "named exports."

### ESM Import Variations

The `import` keyword has a number of variations in syntax. The first is referred to as "named import":

```javascript theme={null}
import { getName } from "/path/to/students.js";

getName(73);   // Suzy
```

This form imports only the specifically named public API members from a module, and adds those identifiers to the top-level scope of the current module.

Multiple API members can be listed inside the `{ .. }` set, separated with commas. A named import can also be *renamed* with the `as` keyword:

```javascript theme={null}
import { getName as getStudentName }
   from "/path/to/students.js";

getStudentName(73);   // Suzy
```

If `getName` is a "default export" of the module:

```javascript theme={null}
import getName from "/path/to/students.js";

getName(73);   // Suzy
```

The only difference here is dropping the `{ }` around the import binding.

By contrast, the other major variation on `import` is called "namespace import":

```javascript theme={null}
import * as Student from "/path/to/students.js";

Student.getName(73);   // Suzy
```

The `*` imports everything exported to the API, default and named, and stores it all under the single namespace identifier as specified. This approach most closely matches the form of classic modules.

## Exit Scope

Whether you use the classic module format (browser or Node), CommonJS format (in Node), or ESM format (browser or Node), modules are one of the most effective ways to structure and organize your program's functionality and data.

<Note>
  The module pattern is the conclusion of our journey in this book of learning how we can use the rules of lexical scope to place variables and functions in proper locations. POLE is the defensive *private by default* posture we always take.

  And underneath modules, the *magic* of how all our module state is maintained is closures leveraging the lexical scope system.
</Note>

That's it for the main text. Congratulations on quite a journey so far! When you're comfortable and ready, check out the appendices, which dig deeper into some of the corners of these topics.
