一 模块模式
JavaScript 模块模式有传统的立即调用函数表达式 (IIFE)、CommonJS、AMD、 ES6 模块
立即调用函数表达式(IIFE)
立即调用函数表达式(IIFE)是一种设计模式,通过创建一个立即执行的函数来封装代码,避免全局命名空间污染。IIFE 结构如下:
(function() {
// 你的代码
})();
它会立即执行,并且所有定义在这个函数内部的变量和函数都是私有的,不会泄露到全局作用域中。
CommonJS
CommonJS 是一种模块规范,主要用于服务器端 JavaScript 环境(如 Node.js)。它定义了如何导出和导入模块,使得 JavaScript 代码可以被组织成模块化的结构。CommonJS 的核心概念是 require 和 module.exports。
导出模块:
使用 module.exports 或 exports 对象来导出模块的内容,使其可以在其他模块中被导入。
// myModule.js
const myFunction = () => {
console.log('Hello from myFunction');
};
module.exports = myFunction;
导入模块
使用 require 函数来引入其他模块。require 会同步地加载模块,并返回模块的导出对象。
// app.js
const myFunction = require('./myModule');
myFunction(); // 输出: Hello from myFunction
工作机制:
-
模块加载:CommonJS 模块是同步加载的。这意味着当你调用 require 时,Node.js 会阻塞代码的执行,直到模块被完全加载并执行完成。
缓存机制: -
加载的模块会被缓存。如果你多次 require 同一个模块,Node.js 会直接从缓存中返回模块,而不是重新加载和执行。这提高了效率并避免了重复加载。
模块作用域: -
每个模块都有自己的作用域。模块内部定义的变量和函数不会污染全局命名空间,只会对模块内部可见。
ES6
ES6 模块(ECMAScript 2015 模块)引入了原生模块化支持,允许使用 import 和 export 语法来组织代码。通过 export 关键字,可以导出函数、对象或变量,而使用 import 关键字,可以在其他模块中导入这些导出的元素
导出模块
// math.js
export function add(x, y) {
return x + y;
}
export function subtract(x, y) {
return x - y;
}
导入模块
// main.js
import { add, subtract } from './math.js';
console.log(add(5, 3)); // 8
console.log(subtract(5, 3)); // 2
CommonJS 与 ES6 模块的区别:
- 加载方式:CommonJS 使用同步加载(适用于服务器端),而 ES6 模块采用异步加载(适用于浏览器环境)。
- 导出与导入: CommonJS 使用 module.exports 和 require,而 ES6 模块使用 export 和 import。
- 静态 vs 动态:ES6 模块是静态的,可以在编译时确定依赖关系,支持更多的静态分析。CommonJS 模块是动态的,依赖关系在运行时确定。
- 模块解析:ES6 模块支持导入和导出重命名、批量导出等更丰富的语法,而 CommonJS 仅支持单一的 module.exports 和 exports 对象。
AMD(ES6已经它替代成为主流)
用于在浏览器端异步加载模块。它最初由 RequireJS 提出的,目的是解决早期 JavaScript 模块化方案中的一些问题,比如依赖管理和异步加载。
定义模块:
使用 define 函数定义一个模块,可以指定该模块的依赖项和模块本身的工厂函数
// math.js
define(['jquery'], function($) {
return {
add: function(a, b) {
return a + b;
},
subtract: function(a, b) {
return a - b;
}
};
});
加载模块:
使用 require 函数来加载模块及其依赖项。require 函数异步加载模块,并在模块加载完成后执行回调函数。
// app.js
require(['math'], function(math) {
console.log(math.add(5, 3)); // 8
console.log(math.subtract(5, 3)); // 2
});
配置
AMD 模块加载器如 RequireJS 允许进行配置,以控制模块的路径、依赖关系等。例如,可以使用 require.config 来设置模块的路径映射:
// main.js
require.config({
paths: {
'math': 'path/to/math',
'jquery': 'path/to/jquery'
}
});
// 加载模块
require(['math'], function(math) {
console.log(math.add(5, 3));
});
缺点:
- 复杂性:需要引入额外的库(如 RequireJS)来管理模块,这可能增加项目的复杂性。
- 配置:可能需要进行额外的配置,尤其是在处理路径和依赖时。