Jacky's blog Jacky's blog
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)

Jacky Wang

行到水穷处,坐看云起时
首页
  • 编码专题
  • 深入浅出 Vite
  • 深入浅出 babel
  • 快速上手API
  • 深入浅出 react
  • Node

    • code-notebook
  • 状态管理

    • redux
  • 前端工程化

    • Wepack
  • React源码

    • React源码
  • 组件库封装

    • 组件库
  • 开发工具

    • Vscode 插件
  • 项目展示
  • 案例中心 (opens new window)
  • First Project
  • 基础算法题
  • 链表题
  • 动态规划
  • 双指针
  • 递归
  • 数据结构
  • 前端学习计划 (opens new window)
  • 技术随笔
  • 转载文章
  • 包管理工具
  • 前端学习周报
  • VSCode插件
  • Promise 专题
  • 函数技巧
  • React 专题
  • 配置文件

    • TSCONFIG-配置 (opens new window)
    • NGINX-配置 (opens new window)
    • 正则规则查询手册 (opens new window)
    • Lint 配置 (opens new window)
  • 教程

    • GIT-教程
    • NPM SCRIPTS-工作流 (opens new window)
    • DOCKER-教程 (opens new window)
    • LERNA-教程 (opens new window)
    • GIT-常用操作整理 (opens new window)
  • VSCode

    • LAUNCH.JSON (opens new window)
  • 指令

    • NPM 指令 (opens new window)
    • NVM 指令 (opens new window)
    • Nginx 指令 (opens new window)
    • YARN 指令 (opens new window)
    • PNPM 指令 (opens new window)
  • 库

    • FS-EXTRA 库 (opens new window)
    • NODE 库-PATH (opens new window)
  • 永远的神

    • 魔法师卡颂-自顶向下学 React 源码 (opens new window)
    • 全栈潇晨 (opens new window)
    • 博客-程序员山月-Daily (opens new window)
    • 淘系前端:冴羽 (opens new window)
  • 系列文章

    • 《图解HTTP》 (opens new window)
    • 《ES6标准入门》 (opens new window)
    • 《现代JavaScript教程》 (opens new window)
    • 《深入浅出Webpack》 (opens new window)
    • VSCode 插件系列:小茗同学 (opens new window)
    • JEST 教程 (opens new window)
    • 前端精读周刊:各种精读系列 (opens new window)
    • 一文吃透系列 (opens new window)
    • 图解 REACT 原理 (opens new window)
  • 实用网站

    • MDN (opens new window)
    • CAN I USE (opens new window)
    • TYPESCRIPT-ESLint-RULES (opens new window)
    • ESLint-RULES (opens new window)
    • FRONT-END TREND (opens new window)
    • NPM TREND (opens new window)
    • 在线分析 Node 依赖 (opens new window)
    • FIND NPM (opens new window)
    • CODE PEN (opens new window)
    • 印记中文 (opens new window)
    • TOOL.LU (opens new window)
    • 阮一峰-网道 (opens new window)
    • DIGITAL OCEAN (opens new window)
    • DEVDOCS.IO (opens new window)
    • JOI (opens new window)
  • 算法

    • 小浩算法 (opens new window)
    • LABULADONG 的算法小抄 (opens new window)
    • 力扣 SOLUTION (opens new window)
    • HACKER RANK (opens new window)
    • 代码随想录 (opens new window)
  • 博客系列

    • 美团大佬 (opens new window)
    • 蜡笔小伟 (opens new window)
    • 优秀博客1 (opens new window)
    • 优秀博客2-umi (opens new window)
    • 优质博客 (opens new window)
  • CSS

    • CSS-EASING 库 (opens new window)
    • ROUGH.JS (opens new window)
    • CSS 网站收集
    • UNOCSS (opens new window)
  • 前端

    • PROMISE (opens new window)
    • UNDERSCORE.JS (opens new window)
    • study with BGM (opens new window)
    • nginx【B站视频】 (opens new window)
    • 机器学习
    • Js基础
  • 掘金已购课程

    • 前端自动化测试精讲 (opens new window)
    • 深入浅出 Vite (opens new window)
    • 现代 Web 布局 (opens new window)
    • 前端算法与数据结构 (opens new window)
    • 基于 Vite 的 SSG 框架开发实战 (opens new window)
    • SSR 实战:官网开发指南 (opens new window)
    • WebGL 入门与实践 (opens new window)
    • 玩转 CSS 的艺术之美 (opens new window)
    • 前端调试通关秘籍 (opens new window)
    • React 进阶实践指南 (opens new window)
    • TypeScript 全面进阶指南 (opens new window)
    • 前端缓存技术与方案解析 (opens new window)
    • npm scripts 前端工作流 (opens new window)
    • Webpack5 核心原理与应用实践 (opens new window)
  • 购物车

    • 张鑫旭-技术写作指南 (opens new window)
    • 深入剖析 Node.js 底层原理 (opens new window)
    • 前端开发者的现代 C++ 课 (opens new window)
    • 从前端到全栈 (opens new window)
  • 分类
  • 标签
  • 归档
GitHub (opens new window)
  • 技术随笔

    • git教程
    • 前端模块化:CommonJS,AMD,CMD,ES6
    • 如何动态加载本地图片
    • GitHub自动部署脚本
    • React生命周期详解
    • 将父组件的props作为组件的初始state的几种方案
    • webpack基础入门
    • StackOver记录:如何在function中使用redux
    • React中使用onClick时的三种性能优化
    • 思考React状态管理
    • forEach/for..in/of
    • styled-components使用记录
    • 深入理解forEach与forof
    • Node技术架构
    • Redux、Mobx状态管理杂谈
    • JS中的类型检测
    • 如何判断图片是否在可视区域
    • 如何使用图片的懒加载操作
    • JavaScript模块化:从CommonJS到AMD
      • 0.前言
      • 1.模块化需要做到什么?
        • 改进1:块级作用域
        • 改进2:使用立即执行函数,形成一个闭包
        • 改进3:修改立即执行函数,使其接受参数
        • 技巧:导入全局变量,并重命名
      • 2. 从服务端到浏览器端的模块化演进
        • AMD:服务端模块化
      • 扩展阅读:AMD详细使用
    • git查看:修改用户名、密码
    • 保持数据Immutable的几种写法
    • 如何实现一个Promise.all
    • resolve(Promise对象)会多出两个微任务
    • todo_基于Mocha的测试驱动开发
    • 浏览器页面渲染机制
    • todo-响应式编程之数据劫持
    • todo-immer库的介绍
    • React-Hooks 基础原理解析
    • JS基本功
    • 函数闭包与this指针
    • 收集 DUMI 配置过程中遇到的问题
    • typescript 类型工具
    • 统一接口的导入导出
    • 网络安全:如何预防 XSS 攻击
    • 浏览器页面渲染机制【2023】
    • 跨域资源请求
    • 浏览器事件循环机制
    • 如何理解浏览器的 user agent 用户代理的含义?
  • 转载文章

  • Mac相关

  • 前端学习周报

  • 包管理工具

  • 技术随笔
  • 技术随笔
wangjiasheng
2022-02-07
目录

JavaScript模块化:从CommonJS到AMD

# 0.前言

本篇博客为阮一峰对JavaScript模块化的两篇文章的读书笔记。

  1. Javascript模块化编程(一):模块的写法 (opens new window)
  2. Javascript模块化编程(二):AMD规范 (opens new window)

# 1.模块化需要做到什么?

阮一峰在第一篇文章探讨的一个问题,模块化需要做到哪儿些要求?

主要需要满足几点要求:

  1. 不能"污染"全局变量,保证不与其他模块发生变量名冲突。
  2. 模块成员之间需要有关联。

如下面这个例子中,函数m1()和m2()简单组合,形成一个模块。

function m1(){
  //...
}

function m2(){
  //...
}
1
2
3
4
5
6
7

上面的代码就是最简单的模块化,但是存在几点问题:

1、变量存放在全局变量中,无法保证m1和m2变量名是否与外部变量重名。

2、无法按需导出,模块中的所有变量(Context)被注入到全局环境中,无法保护私有变量的不被修改。

3、模块与模块之间无法做到关联,如A模块的变量需要依赖于B模块已经加载完成。

# 改进1:块级作用域

使用对象的方式,主动创建一个全新的作用域

var module1 = new Object({
  _count : 0,

  m1 : function (){
    //...
  },

  m2 : function (){
    //...
  }

});
1
2
3
4
5
6
7
8
9
10
11
12

调用时,就是调用这个对象的属性。

module1.m1();
1

缺点:会暴露所有的模块成员,内部状态可以被外部改写。如下:

module1._count = 5;
1

# 改进2:使用立即执行函数,形成一个闭包

原文:使用"立即执行函数 (opens new window)"(Immediately-Invoked Function Expression,IIFE),可以达到不暴露私有成员的目的。

闭包可以同时达到形成了一个全新的变量空间,以及按需暴露变量的目的。

var module1 = (function(){

  var _count = 0;

  var m1 = function(){
    //...
  };

  var m2 = function(){
    //...
  };

  return {
    m1 : m1,
    m2 : m2
  };

})();
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

使用上面的写法,外部代码无法读取内部的_count变量。

console.info(module1._count); //undefined
1

但是,这种写法仍有缺陷,就是使用立即执行函数形成的封闭的上下文(Context),是一个全新的内存空间,模块化还需要接入其他模块的环境(Context)的功能。

# 改进3:修改立即执行函数,使其接受参数

阮一峰将其称为:放大模式与宽放大模式

// 1. 放大模式:
var module1 = (function (mod){

  mod.m3 = function () {
    //...
  };

  return mod;

})(module1);

// 2. 宽放大模式:就是兼容性处理 || {}
var module1 = ( function (mod){
  //...
  return mod;

})(window.module1 || {});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 技巧:导入全局变量,并重命名

下面的module1模块需要使用jQuery库和YUI库,就把这两个库(其实是两个模块)当作参数输入module1。

var module1 = (function ($, YAHOO) {

  //...

})(jQuery, YAHOO);
1
2
3
4
5

以上的写法:保证模块的独立性,还使得模块之间的依赖关系变得明显。

# 2. 从服务端到浏览器端的模块化演进

对于模块化而言,规范有很多,例如:CommonJS、AMD、CMD、ES6。区别主要在于几点:导入和导出。

导入的方式:可以是记录引用地址(ES6),也可以直接将环境全部存入内存中(require)。

导出的方式:需要将私有环境和导出的变量分区分开来,如上面介绍使用立即执行函数+return的导出方式。

不同模块化规范,其实对应着不同的使用环境。如:

  • CommonJs:Node环境/服务端环境。
  • AMD:特点是模块的异步导入,特别适合需要HTTP请求的浏览器环境。
  • CMD:不清楚。
  • ES6:兼容服务器环境与浏览器环境。

下面的代码适合在服务端运行, 在浏览器端也可以运行,只不过代码同步执行的时间太久了(假死状态)。

// CommonJS规范 在Node环境中执行下面这段代码没有问题
var math = require('math');
math.add(2,3); // 这段代码必须要等math.js加载完成后蔡奶奶个执行
1
2
3

由于服务器端math.js就是存在本地硬盘,所以代码同步执行是没有问题的,但是,对于浏览器,这却是一个大问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于"假死"状态。

# AMD:服务端模块化

AMD (opens new window)是"Asynchronous Module Definition"的缩写,意思就是"异步模块定义"。

异步通过回调函数实现。

回调函数的本质:提前定义,延时调用(函数的触发不由我们控制,而是等待程序执行后触发)。

AMD也采用require()语句加载模块,但是不同于CommonJS,它要求两个参数:

require([module], callback);
1

第一个参数[module],是一个数组,里面的成员就是要加载的模块;第二个参数callback,则是加载成功之后的回调函数。如果将前面的代码改写成AMD形式,就是下面这样:

require(['math'], function (math) {
  math.add(2, 3);
});
1
2
3

目前,主要有两个Javascript库实现了AMD规范:require.js (opens new window)和curl.js (opens new window)。

# 扩展阅读:AMD详细使用

  1. https://juejin.cn/post/6844903576309858318 (opens new window)
编辑 (opens new window)
上次更新: 2022/04/06, 15:04:00
如何使用图片的懒加载操作
git查看:修改用户名、密码

← 如何使用图片的懒加载操作 git查看:修改用户名、密码→

最近更新
01
如何理解浏览器的 user agent 用户代理的含义?
11-05
02
浏览器事件循环机制
10-31
03
浏览器页面渲染机制【2023】
10-15
更多文章>
Theme by Vdoing | Copyright © 2020-2023
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式