对CommonJS的理解

45 阅读2分钟

一、模块的导出

1.1 什么是模块

模块是一个JS文件,它实现了部分功能并隐藏自己的内部实现,同时提供了一些接口供外部使用。

任何一个正常的模块化标准,都应该默认隐藏模块的所有实现,而通过一些语法或api调用来暴露接口。

function getNumber() {
	var num = 0
	return function () {
		return num++
	}
}
var fn = getNumber()

二、模块的导入

当通过某种语法或api去使用一个模块时,这个过程叫做模块的导入。

三、CommonJS规范

CommonJS使用·exports·导出模块,·require·导入模块

具体规范如下:

  1. 如果一个JS文件中存在exportsrequire,该JS文件是一个模块。
  2. 模块内的所有代码均为隐藏代码,包括全局变量、全局函数,这些全局的内容均不应该对全局变量造成任何污染。 3.如果一个模块需要暴露一些API提供给外部使用,需要通过exports导出,exports是一个空的对象,你可以为该对象添加任何需要导出的内容。
  3. 如果一个模块需要导入其他模块,通过require实现,require是一个函数,传入模块的路径即可返回该模块导出的整个内容。
function getNumber() {
	var num = 0
	return function () {
		return num++
	}
}
var fn = getNumber()
exports.fn = fn
// nodejs导入模块,使用相对路径,并且必须以./或者../开头
const utils = require('./utils.js')

四、nodejs对CommonJS的实现

为了实现CommonJS规范,nodejs对模块做出了以下处理

  1. 为了保证高效的执行,仅加载必要的模块。nodejs只有执行到require函数时才会加载并执行模块
  2. 为了隐藏模块中的代码,nodejs执行模块时,会将模块中的所有代码放置到一个函数中执行,以保证不污染全局变量。
(function(){
  //模块中的代码
})()
  1. 为了保证顺利的导出模块内容,nodejs做了以下处理 1.在模块开始执行前,初始化一个值module.exports = {} 2. module.exports即模块的导出值 3. 为了方便开发者便捷的导出,nodejs在初始化完module.exports后,又声明了一个变量exports = module.exports
(function(module){
  module.exports = {};
  var exports = module.exports;
  //模块中的代码
  return module.exports;
})()
  1. 为了避免反复加载同一个模块,nodejs默认开启了模块缓存,如果加载的模块已经被加载过了,则会自动使用之前的导出结果。