CommonJs,Requirejs和ES6
CommonJs,Requirejs和ES6模块的使用。
CommonJs
commonjs是nodejs这也就是服务器端广泛使用的模块化机制。
该规范的主要内容是,模块必须通过module.exports导出对外的变量或接口,通过require()来导入其他模块的输出到当前模块的作用域中
根据这个规范,每个文件就是一个模块,有自己的作用域,文件中的变量,函数,类等都是对其他文件不可见的,如果想在多个文件分享变量,必须定义为global对象的属性(不推荐)
定义模块
在每个模块内部,module变量代表当前模块,它的exports属性时对外的接口,将模块的接口暴露出去。其他文件加载该模块,实际上就是读取module.exports变量
加载模块
,后缀名默认为js
模块的加载顺序,按照其在代码中的出现顺序
根据require的参数不同,require命令回去不同的路径寻找模块文件
(1)如果参数字符串以 / 开头,则表示加载的是一个位于绝对路径的模块文件
(2)如果参数字符串以 ./ 开头,则表示加载的是一个位于相对路径的模块文件
(3)如果参数字符串不以上述两种方式开头,表示加载的是一个默认提供的核心模块(node核心模块,或者通过全局安装或局部安装在node_modules中的模块)
入口文件
一般都会有一个主文件(入口文件),在index.html中加载这个入口文件,然后在这个入口文件中加载其他文件,可以在package.json中配置main字段指定入口文件
模块缓存
第一次加载某个模块时,Node会缓存该模块,以后再加载该模块,就直接从缓存中取出该模块的module.exports
加载机制
CommonJS的加载机制是,输入的是被输入值的拷贝,也就是一旦输出了一个值,模块内部的变化就影响不到这个值
AMD
AMD(异步模块定义)是为浏览器环境设计的,因为commonjs模块系统是同步加载的,当前浏览器环境还没有准备好同步加载模块的条件
定义模块
define方法用于定义模块,RequireJS要求每个模块放到一个单独的文件中
按照是否依赖其他模块,可以分为两种,第一种是定义独立模块,第二种是定义非独立模块
独立模块
1 | define(function () { |
非独立模块
1 | define(['module1', 'module2'], function (m1, m2) { |
加载模块
使用require方法加载模块,但由于是异步的因此使用回调函数的形式
1 | require(['m1', 'm2'], function (m1, m2) { |
上述代码表示加载m1和m2两个模块,当加载成功之后,执行回调函数,该回调函数就用来完成具体的任务
require方法也可以用在define方法内部
1 | define(function(require) { |
require方法也支持第三个参数,即错误处理的回调函数
1 | require( |
配置
require方法本身也是一个对象,它有一个config方法,用于配置require.js的参数
1 | require.config({ |
paths
paths参数指定各个模块的位置,这个位置既可以是同一个服务器上的位置,也可以是外部网址,也可以为同一个模块定义多个位置,这样当第一个位置加载失败,会加载第二个位置。上述代码指定了jquery的位置,这样在文件中就可以直接在文件中直接使用require([‘jquery’], function(){})了
shim
有些库是AMD不兼容的,所以就需要指定shim属性,该属性用于帮助AMD加载非AMD规范的库
1 | require.config({ |
ES6 Modules
ES6正式提出了内置的模块化语法,我们在浏览器端无需额外引入requirejs来进行模块化。
ES6中的模块有以下特点:
模块自动运行在严格模式下
在模块的顶级作用域创建的变量,不会被自动添加到共享的全局作用域,它们只会在模块顶级作用域的内部存在;
模块顶级作用域的 this 值为 undefined
对于需要让模块外部代码访问的内容,模块必须导出它们
定义模块
使用export关键字将任意变量,函数或者类公开
1 | //导出变量 |
重命名模块
1 | function sum(num1, num2) { |
导出默认值
模块的默认值是使用 default 关键字所指定的单个变量、函数或类,而你在每个模块中**只能设置一个默认导出。
1 | export default function(num1, num2) { |
此模块将一个函数作为默认值进行了导出, default 关键字标明了这是一个默认导出。此函数并不需要有名称,因为它就代表这个模块自身。对比最前面使用export导出的函数,并不是匿名函数而是必须有一个名称用于加载模块的时候使用,但是默认导出则无需一个名字,因为模块名就代表了这个导出值。
也可以使用重命名方法导出默认值
1 | function sum(num1, num2) { |
加载模块
在模块中使用import关键字来导入其他模块。
import 语句有两个部分,一是需要导入的标识符,二是需导入的标识符的来源模块。此处是导入语句的基本形式:
1 | import { identifier1,identifier2 } from "./example.js" |
重命名导入
与导出相同,我们同样可以重命名导入的绑定:
1 | import { sum as add} from './example.js' |
限制
export 与 import 都有一个重要的限制,那就是它们必须被用在其他语句或表达式的外部,而不能使用在if等代码块内部。原因之一是模块语法需要让 JS 能静态判断需要导出什么,正因为此,你只能在模块的顶级作用域使用 export与import。
参考文章: