2-2CommonJS
CommonJS
在nodejs中,由于有且仅有一个入口文件(启动文件),而开发一个应用肯定会涉及到多个文件配合,因此,nodejs对模块化的需求比浏览器端要大的多
由于nodejs刚刚发布的时候,前端没有统一的、官方的模块化规范,因此,它选择使用社区提供的CommonJS作为模块化规范
在学习CommonJS之前,首先认识两个重要的概念:模块的导出和模块的导入
模块的导出
要理解模块的导出,首先要理解模块的含义
什么是模块?
模块就是一个JS文件,它实现了一部分功能,并隐藏自己的内部实现,同时提供了一些接口供其他模块使用
模块有两个核心要素:隐藏和暴露
隐藏的,是自己内部的实现
暴露的,是希望外部使用的接口
任何一个正常的模块化标准,都应该默认隐藏模块中的所有实现,而通过一些语法或api调用来暴露接口
暴露接口的过程即模块的导出
模块的导入
当需要使用一个模块时,使用的是该模块暴露的部分(导出的部分),隐藏的部分是永远无法使用的。
当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入
CommonJS规范
CommonJS使用exports导出模块,require导入模块
具体规范如下:
1.如果一个JS文件中存在exports或require,该JS文件是一个模块
模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染
2.如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容
3.如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容
nodejs对CommonJS的实现
为了实现CommonJS规范,nodejs对模块做出了以下处理
1.为了保证高效的执行,仅加载必要的模块。nodejs只有执行到require函数时才会加载并执行模块
2.为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量。
(function(){
//模块中的代码
})()
为了保证顺利的导出模块内容,nodejs做了以下处理
在模块开始执行前,初始化一个值module.exports = {}
module.exports即模块的导出值
为了方便开发者便捷的导出,nodejs在初始化完module.exports后,又声明了一个变量
exports = module.exports
(function(module){
module.exports = {};
var exports = module.exports;
//模块中的代码
return module.exports;
})()
为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果
4-1ES6模块化
// ES模块化
// 1.使用依赖“预声明”的方式导入模块
// (1)依赖延迟声明
// 1)优点:某些时候可以提高效率
// 2)缺点:无法在一开始确定模块依赖关系(比较模糊)
// (2)依赖预声明
// 1)优点:在一开始就可以确定依赖关系
// 2)缺点:某些时候效率很低
// 2.灵活的多种导入方式
// 3.规范的路径表示法:所有的路径必须以./或../开头
4-2基本导入导出
// ES6中模块导入导出分为两种
// 1.基本导入导出
// 导出 (1)export 声明表达式
export let a = 1;//导出a=1;类似于CommonJS中的exports.a = 1;
export function test(){//类似于exports.test = function(){}
}
export class Person{
}
export const name = 'abc';
// (2)export{具名符号}
let age = 18;
let sex = 1;
export {age,sex}//将age变量的名称作为导出的名称,将age变量的值作为导出的值
// 导入 由于使用的是*依赖预加载*,因此,导入任何其他模块,导入代码必须放入到其他代码之前
// import{导入的符号列表} from '模块路径'
import {name,age} from './a.js';
// 导入重命名
import {name as name1} from './a.js'
console.log(name1);
// 导入使用的符号是常量不可以修改
// 可以使用*导入所有的基本导入,形成一个对象
import * as obj from './a.js';
4-3默认导出导入
// 2.默认导入导出
// 默认导出类似于CommonJS中的module.export由于只有一个无需具名
/**export default 默认导出的数据
*或
export{默认导出的数据 as default}*/
export let a = 1;
export default a;
// 默认导入
/**
* import 接收变量名 from '模块路径'
* 类似于Common JS 中的
* let 接收变量名 = require('模块路径')
* /