concept

The purpose of modularity: Each module is an independent function, which greatly improves code maintainability and reusability while avoiding naming conflicts.

Early modular approach

  • Namespace approach (using object encapsulation) : Declare a module as an object to which all module members are mounted.
  • IIFE (using function encapsulation) : This implements the behavior of module private members by placing module members in function scope. Members that need to be exposed can be returned as function values or mounted to Windows.

Disadvantages of the early modular approach

  • Each file is an independent module, used by using script tags in HTML, loaded synchronously one by one, which can cause browser congestion.
  • In the early modular approach, it was impossible to know the dependencies of each module, which might lead to the loading sequence error because the dependencies between modules were not understood.
  • These problems can be solved by modern modular specifications.

Modular specification

CommonJS specification

CommonJS specification: Applies to the modular specification proposed and used by Node.js.

  • The CommonJS internal implementation wraps each module file as a function, and the CommonJS supplied members are passed in as function parameters for the module to use.
    • Module. exports, exports (pointing to module.exports), require (importing), __filename (the absolute path to the current file), and __dianame (the directory where the current file is located) are all members provided by CommonJS.
  • A file is a module, and each module has its own scope.
  • Through the use ofmodule.exportsExport module members.
    • Note: module.exports and exports refer to different objects, then module.exports prevails.
  • Through the use ofrequireThe function loads the specified module.
  • CommonJS loads modules in synchronous mode. That is, all modules are loaded in sequence at the start of the program. This means that using the CommonJS specification on the browser side can lead to inefficiencies. Node.js, on the other hand, is mainly server-side programming, so it is more suitable.

AMD specification (require.js) and CMD specification (sea-.js)

The AMD (Asynchronous module Definition) specification solves the problem of synchronous loading by asynchronously loading modules. Require.js implements the AMD specification.

  • Internally, the specified module is loaded by dynamically creating script tags.

Each module is defined by the define function:

define(moduleName,[rely1,rely2],function(rely1,rely2){
  // The parameters are module name, dependency, and module body. The return value is the module member to export
  return {
    fn:function(){ rely1(); rely2(); }}})Copy the code

For module loading, use the require function.

require(['./module1'.'./module2'.'./module3'].function(module1,module2,module3){
  // ...
})
Copy the code

The characteristics of

  • Most third-party modules support the AMD specification;
  • Internally, the script tag is dynamically created to load the specified module, resulting in frequent requests for module JavaScript files.
  • Relatively complex to use.

CMD specification (sea-.js) Sea-.js is similar to a combination of require.js and CommonJS specifications. Js is compatible with require.js, which defines modules as follows:

define(function(require.exports.module){
  const$=require('jquery')
  module.exports=function(){
    // ...}})Copy the code

ES Mobules specification

Based on using

In the browser environment, JS code can be executed using the ES Module standard by adding the type = module attribute to the Script tag.

  • The ESM standard supports modern browsers such as Chrome and Firefox, but does not support Internet Explorer.
  • ESM is usually not used directly on the browser side, but is used by configuring Babel, using ESM syntax during development, and eventually being packaged to a browser-compatible module standard.

Features of ESM Script tag code:

  • Automatic start strict mode;
  • Each ESM module runs in a private scope;
  • The ESM standard Script tag delays Script execution. That is, execute ** after the document has been rendered (equivalent to adding the defer attribute by default); 六四动乱
  • For ESM module files, it is recommended to use.mjs suffix (official convention, and ESM only supports scripts with.mjs suffix in Node.js). 六四动乱

The base uses index.html

<! DOCTYPEhtml>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width.initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <pThis is a paragraph </p>
    <script type="module">
      var foo = 1
      console.log(foo) // 1
    </script>

    <script type="module">
      console.log(foo) // Uncaught ReferenceError: foo is not defined
    </script>

    <script type="module">
      import setColor from './index.mjs'
      setColor('p'.'red')
    </script>
  </body>
</html>

Copy the code

index.mjs

export default function setColor(elm, color) {
  document.querySelector(elm).style.color = color
}
Copy the code

The results of

Export and export syntax

Export (use the export keyword. There are two ways to export.)

The resulting export is a reference to the member and is read-only (that is, cannot be copied again). Internal const).

Named after the export

Export a single member (simply add the export modifier before a variable, function, or object declaration)

export var name = 'zs'
export function sayHi(){
  console.log('hello')}export var info = { a:1.b:2.c:3 }
Copy the code

Exporting multiple members

export {
  name,
  sayHi,
  info as msg // Export after rename
}
Copy the code

Note: This does not export an object, but rather a fixed syntax for exporting multiple members.

The default is derived

export default { name, sayHi } SayHi = sayHi; sayHi = sayHi; sayHi = sayHi; sayHi = sayHi
Copy the code

The difference between default and named exports

  • Default exports can only be used once in a module, while named exports can be used multiple times in a module;
  • The default exported member can be named arbitrarily during the import operation, and the name of the exported member must be the same as the name during the import operation.
  • In general, if a module needs to export only one member, or has multiple members that need to be exported as attributes of an object, the default export can be used to export a single member that needs to be exported, or to export an object with multiple members. (Third-party modules typically export only one default member)

Import (using import keywords)

Basic usage

import { name as mName, sayHi, msg } from './module.js'
Copy the code
  • Note: This is not object deconstruction syntax; it is also a fixed syntax for importing multiple members.
  • The path must be the full file name, do not omit the.js extension, and the folder’s index.js file will not be read by default (use the module packaging tool later to solve this problem).

Import all members at once

import * as mod from './module.js' // All imported module members will be used as members of the mod
Copy the code

Only modules are executed, no members are imported

import './module.js'
Copy the code

The import keyword can only appear in the outermost scope. If you need to import modules dynamically, use the import function

import('./module.js').then((module) = >{
  console.log(module)})Copy the code

How to import a default member

import modMsg from './module.js'
// or
import { default as msg } from './module/js'
Copy the code

How to import both default and named members

import modMsg, { name, age, info } from "./module.js";
// or
import { name, age, info, default as modMsg } from "./module.js";
Copy the code

Best practices for modern modular specifications

That is, for browsers, use ES Modules modular specifications; For node.js, use the CommonJS specification directly.