模块化,就是将一个完整的项目分成几个模块,每一个模块可以单独运行,并且每个模块只负责一项功能。
模块化四部分:模块定义,接口暴露,模块引入,模块调用
模块化开发是一种管理方式,是一种生产方式,一种解决问题的方案,一个模块就是实现特定功能的文件,
因为有了模块,我们就可以更方便地使用别人的代码,想要什么功能,就加载什么模块。
JavaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,
我们称为模块化。
在node.js中,模块就是一个文件,通常js、json文件,包是多个模块的集合,类似文件夹。
Reactjs里的模块/组件:就是将一段js、html、css组合在一起,形成有一定功能的代码片段
但是,这样是有规范的,于是下面三个模块规范出来了:
CommonJS:
一开始大家都认为JS是辣鸡,没什么用,官方定义的API只能构建基于浏览器的应用程序
然后CommonJS就出来了CommonJS API定义很多普通应用程序,主要指非浏览器的应用
使用的API,从而填补了这个空白。它的终极目标是提供一个类似Python,Ruby和Java标准库。
这样的话,开发者可以使用CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。
node.js的模块系统,就是参照CommonJS规范实现的。在CommonJS中,有一个全局性方法require(),用于加载模块。
CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}
require()用来引入外部模块;exports对象用于导出当前模块的方法或变量,唯一的导出口;module对象就代表模块本身。
AMD:
AMD 的 API 默认是一个当多个用
基于commonJS规范的nodeJS出来以后,服务端的模块概念已经形成,很自然地,大家就想要客户端模块。而且最好两者能够兼容,
一个模块不用修改,在服务器和浏览器都可以运行。但是,由于一个重大的局限,使得CommonJS规范不适用于浏览器环境。就是
如果加载时间很长,整个应用就会停在那里等。require 是同步的。
这对浏览器是个很大的问题,因为模块都放在服务器端,等待时间取决于网速的快慢,可能要等很长时间,浏览器处于“假死”状态。
AMD是"异步模块定义"。它采用异步方式加载模块,模块的加载不影响它后面语句的运行。所有依赖这个模块的语句,都定义在一个
回调函数中,等到加载完成之后,这个回调函数才会运行。
模块功能主要的几个命令:define、require、return和define.amd。define是全局函数,用来定义模块,
define(id, dependencies, factory)。
require命令用于输入其他模块提供的功能,return命令用于规范模块的对外接口,define.amd属性是一个对象,此属性的存在来
表明函数遵循AMD规范。
CMD:
玉伯写了seajs,就是遵循他提出的CMD规范,与AMD蛮相近的
(Common Module Definition - 通用模块定义)规范主要是Sea.js推广中形成的,一个文件就是一个模块,可以像Node.js一般书写
模块代码。主要在浏览器中运行,当然也可以在Node.js中运行。
CMD 的 API 严格区分,推崇职责单一。
CMD 里提供 seajs.use 来实现模块系统的加载启动。CMD里,每个 API 都简单纯粹。
SeaJS 是一个适用于 Web 浏览器端的模块加载器。使用 SeaJS,可以更好地组织 JavaScript 代码 虽然CMD与AMD蛮像的,
但区别还是挺明显的
两者的主要区别如下:
1. 定位有差异。RequireJS 想成为浏览器端的模块加载器,同时也想成为 Rhino / Node 等环境的模块加载器。
Sea.js 则专注于 Web 浏览器端,同时通过 Node 扩展的方式可以很方便跑在 Node 环境中。
2. 遵循的规范不同。RequireJS 遵循 AMD(异步模块定义)规范,Sea.js 遵循 CMD (通用模块定义)规范。规范的不同,
导致了两者 API 不同。Sea.js 更贴近 CommonJS Modules/1.1 和 Node Modules 规范。
3. 推广理念有差异。RequireJS 在尝试让第三方类库修改自身来支持 RequireJS,目前只有少数社区采纳。Sea.js 不强推,
采用自主封装的方式来“海纳百川”,目前已有较成熟的封装策略。
4. 对开发调试的支持有差异。Sea.js 非常关注代码的开发调试,有 nocache、debug 等用于调试的插件。RequireJS 无这方面的明显支持。
5. 插件机制不同。RequireJS 采取的是在源码中预留接口的形式,插件类型比较单一。Sea.js 采取的是通用事件机制,插件类型更丰富。
UMD:
UMD:是(通用模块规范)是由社区想出来的一种整合了CommonJS和AMD两个模块定义规范的方法。
人们想出这个UMD模式,希望解决跨平台的解决方案。
UMD先判断是否支持Node.js的模块(exports)是否存在,存在则使用Node.js模块模式。
在判断是否支持AMD(define是否存在),存在则使用AMD方式加载模块。
基本原理:
用一个工厂函数来统一不同的模块定义规范。
原则:
所有定义模块的方法需要单独传入依赖
所有定义模块的方法都需要返回一个对象,供其他模块使用
es6:
es6在语言标准的层面上,实现模块的功能,而且实现的相当简单,
其模块的功能主要的两个命令:export和import。
export 命令用于 命令用于规定模块的对外接口,
import命令用于输入其他模块提供的功能。
ES6的模块不是对象,import命令会被 JavaScript 引擎静态分析,在编译时就引入模块代码,而不是在代码运行时加载,所以无法实现条件加载。
使用模块化的优点:
- 模块化便于多人协作开发,每个部分开发不会干扰其它地方
- 便于调试修改,因为模块独立,发现问题比较容易,修改一处,也不影响别处
- 利于代码复用,小块的代码可以更方便拿到别的项目中不加或者稍加修改使用
- 便于功能的扩充,因为软件各个部分是独立的,不需要理解整个软件就可以添加功能,特别适合二次开发。
使用模块化的缺点:
污染了全局变量,无法保证不与其他模块发生变量名冲突,而且模块成员之间没什么关系