Nodejs之CommonJS规范(一)

  • Post author:
  • Post category:其他




Commonjs规范

  1. 关于CommonJS规范
  • 诞生的目的就是为了弥补浏览器没有模块化缺陷
  • CommonJS是语言层面的规范,是一个超集,当前主要用于Nodejs
  • CommonJS规范规定模块化分为引入(通过rrquire导入其他模块)、定义(任意一个文件就是一个模块,具有独立作用域)、标识符(将模块ID传入require实现目标模块定位)三个部分
  1. module属性
  • 任意js文件就是一个模块,可以使用module属性
  • id:返回模块标识符,一般是一个绝对路径
  • filename:返回文件模块的绝对路径
  • loaded:返回布尔值,表示模块是否完成加载
  • parent:返回对象,调用当前模块的模块
  • children:返回数组,当前模块要调用的其他模块
  • exports:返回当前模块要暴露的内容
  • paths:返回不同目录下的node_modules位置
  1. module.exports 与exports的区别
  • 在commonjs规范中只规定了使用module.exports导出数据
  • 是nodejs为了方便,给每个模块加了一个exports指向module.exports的内存地址
  • 但是不能直接给exports赋值,这样它就指向新的内存地址

在这里插入图片描述

  1. requir属性
  • 基本功能是读入并且执行一个模块文件返回这个对象里的exports对象,如果没有找到该模块会报错

    (加载即执行了吗)
  • resolve:返回模块文件绝对路径
  • extensions:依据不同后缀名执行解析操作,根据不同的后缀名执行不同的执行函数,.js,.json,.node,省略不写会依次判断
  • main:返回主模块对象



导入导出示例

新建module.js文件

const age = 18
const addFN= (x,y)=>{
    return x+y
}
module.exports = {
    addFN,
    age
}

新建01.js文件

let obj = require('./module')
console.log(obj,'oooo') 

执行node 01 得到如下结果:{ addFN: [Function: addFN], age: 18 }

那之前我们说过每个文件都是一个独立的模块,模块内可以使用module属性,那假设我们在01.js中打印module会发生什么呢?

let obj = require('./module')
console.log(module) 

在这里插入图片描述

其中

  • id 是模块标识
  • path是文件所在的父级路径
  • exports是一个对象,代表本模块要导出的内容,这里没有导出故而为空对象
  • parent是指谁引用了我
  • filename是指文件绝对路径
  • loaded是否加载完成
  • children是表明此模块引入了哪些子模块,我们引入了module.js这个模块
  • paths:表示node_modules查找顺序


注意:

  1. exports是nodejs为了方便使用写的语法糖,指向与module.exports同一内存地址,一旦我们对其重新赋值则切断了联系也无法完成导出
//module.js
const age = 18
const addFN= (x,y)=>{
    return x+y
}
exports = {
    addFN,
    age
}
let obj = require('./module')
console.log(obj,'oooo') // 结果为{}
  1. 我们可以通过exports[属性名]的方式进行导出,导出操作是生效的
//module.js
const age = 18
const addFN= (x,y)=>{
    return x+y
}
exports.addFN = addFN
exports.age = age
let obj = require('./module')
console.log(obj,'oooo') // 结果为{ addFN: [Function: addFN], age: 18 } oooo
  1. 如果我们没有导出,则别人加载后是一个{},因为module.exports默认是{}



同步加载

在CommonJS中,非核心模块的加载是同步加载,也就是说假设我们引入的组件耗时,那会等待加载完成继续向下执行。

//module.js
const age = 18
let nTime = new Date()
while(new Date()-nTime<4000){

}
exports.age = age
console.log('页面导出完成')
let obj = require('./module')
console.log('加载完成') 

命令行执行node 01之后是隔4秒钟后打印如下内容:

页面导出完成

加载完成


注意:

  1. 可以判断,我们导入某个模块,是先把模块的内容以同步的方式装载到系统中,如果装载的过程中模块存在问题,则会导致程序中断执行,有点类似于同步引入js的那种感觉
//module.js
const age = 18
age = 20
exports.age = age
//01.js
let obj = require('./module')
console.log(obj) 
console.log('加载完成');

执行结果如下:

在这里插入图片描述

  1. 如果要加载多个模块,需要加载完第一个模块才会加载后续模块,在浏览器中同步加载会导致性能低下,因此不适合于浏览器



版权声明:本文为liuliuliuliumin123原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。