一文搞懂CommonJs规范

  • Post author:
  • Post category:其他



CommonJS是


一个规范


,最初提出来是在浏览器以外的地方使用,并且当时被命名为



ServerJS



,后来为了 体现它的广泛性,修改为



CommonJS



,平时我们也会

简称为CJS

CommonJS规范规定,每个模块内部,

module

变量代表当前模块。这个变量是一个对象,它的

exports

属性(即

module.exports

)是对外的接口。加载某个模块,其实是加载该模块的

module.exports

属性。

Node中对CommonJs进行了支持和实现,让我们在开发Node过程中更方便的进行模块化开发
  • 在Node中每一个Js文件都是一个模块
  • 这个模块中包含CommonJs规范核心变量:exports、module.exports、require

先来看下面两个文件,bar.js、main.js


在main.js中想要输出并运行bar.js中的变量和函数,但是在执行的时候首先会因为找不到name这个变量而抛出异常。

因此main.js模块要想用到bar.js中的东西,bar.js这个模块就必须导出自己的内容

exports导出

exports是一个对象,我们可以在这个对象上添加很多属性

bar.js模块中通过 exports 对象导出

const name = "deyang";
const age = 18;

let message = "hello javascript";
function sayHello() {
    console.log(message)
}

// 将需要到处的内容,添加到exports对象上
exports.name = name;
exports.age = age;
exports.sayHello = sayHello;

main.js模块中通过 require() 导入

const bar = require("./bar");

console.log(bar.name);
console.log(bar.age);
bar.sayHello();


// 也可以直接将导出对象结构获取变量,但不推荐,使用的时候变量来源不清晰
// const { name, age, sayHello } = require("./bar");

// console.log(name);
// console.log(age);
// sayHello();

此时 main.js模块就能顺利获取bar模块的变量方法。这是因为,Node中实现Commonjs规范的本质是对象的引用赋值

下面附上本人珍贵手图

bar.js中的exports对象 和 main中通过require(‘./bar’) 的返回值其实是同一个对象,所以 bar 对象是exports对象的浅拷贝(引用赋值)

So、What is the module.exports ?

我们在Node中导出东西的时候又是通过 module.exports 导出的

module.exports  和 exports 之间的关系又是什么呢?

维基百科对CommonJs的解释:


  • CommonJS中是没有module.exports的概念的;

  • 为了实现模块的导出,Node中使用的是Module的类,每一个模块都是Module的一个实例,也就是


    module;

  • Node中真正用于导出的其实根本不是exports,而是module.exports;

但是为什么 exports 也可以导出呢?

因为Node源码中做了以下操作

modulex.exports = exports;

所以 module对象的export属性 是exports 对象的一个引用,真正导出还是看module.exports的

如果改变module.exports对象会发生什么?结果将是翻天覆地的变化


const name = "deyang";
const age = 18;

let message = "hello javascript";
function sayHello() {
    console.log(message)
}


exports.name = name;
exports.age = age;
exports.sayHello = sayHello;

module.exports = {
    name: "寒冰射手",
    age: 99,
    sayHello:  function() {
        console.log('我可不是个傻瓜')
    }
}
 
module.exports不再引用exports对象了,那么修改export还有意义 ?
此时main.js中导入的内容,以bar.js中module.exports 实际导出的为准。
因此输出的结果如下:



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