02_2node_模块化commonjs

什么是模块化

事实上模块化开发最终的目的是将程序划分成一个个小的结构;

这个结构中编写属于自己的逻辑代码,有自己的作用域,不会影响到其他的结构;

这个结构可以将自己希望暴露的变量、函数、对象等导出给其结构使用;

也可以通过某种方式,导入另外结构中的变量、函数、对象等

上面说提到的结构,就是模块;按照这种结构划分开发程序的过程,就是模块化开发的过程;

没有模块化带来的问题

命名冲突问题

可以用立即执行函数解决,函数有作用域  (function{})()    匿名函数

新的问题:代码较混乱,每个文件里面都要有匿名函数,要记住每个模块返回的对象的命名

所以,模块化已经是JavaScript一个非常迫切的需求:

但是JavaScript本身,直到ES6(2015)才推出了自己的模块化方案;

在此之前,为了让JavaScript支持模块化,涌现出了很多不同的模块化规范:AMD、CMD、CommonJS等

commonjs和node

Node中对CommonJS进行了支持和实现,让我们在开发node的过程中可以方便的进行模块化开发:

在Node中每一个js文件都是一个单独的模块;

这个模块中包括CommonJS规范的核心变量:exports、module.exports、require

exports和module.exports可以负责对模块中的内容进行导出;

require函数可以帮助我们导入其他模块(自定义模块、系统模块、第三方库模块)中的内容

commonjs中的exports

导出的是exports,exports是一个空对象

导出就是往exports里加属性

commonjs中require()

 require()是用来导入的,require()是一个函数,返回的是一个对象

exports导出和require()导入是同一个对象

是一个浅拷贝,引用赋值

module.exports又是什么的? 

module.exports和exports有什么关系或者区别呢?

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

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

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

因为module才是导出的真正实现者;

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

这是因为module对象的exports属性是exports对象的一个引用;

开局module.exports=exports指向同一个对象

也就是说 module.exports = exports = main中的bar;

当用module.exports导出,不在引用exports

当我们用module.exports导出时,相当于给module.exports创建了新的对象,导出的是新对象

就没有exports的事了,不带它玩了

模块的加载过程

结论一:模块在被第一次引入时,模块中的js代码会被运行一次

结论二:模块被多次引入时,会缓存,最终只加载(运行)一次

              这是因为每个模块对象module都有一个属性:loaded。

             为false表示还没有加载,为true表示已经加载

结论三:如果有循环引入,那么加载顺序是什么?

             Node采用的是深度优先算法

CommonJS规范缺点

CommonJS加载模块是同步的:

同步的意味着只有等到对应的模块加载完毕,当前模块中的内容才能被运行;

这个在服务器不会有什么问题,因为服务器加载的js文件都是本地文件,加载速度非常快;

应用于浏览器,浏览器加载js文件需要先从服务器将文件下载下来,之后在加载运行;

那么采用同步的就意味着后续的js代码都无法正常运行,即使是一些简单的DOM操作;

所以在浏览器中,我们通常不使用CommonJS规范:

当然在webpack中使用CommonJS是另外一回事;

因为它会将我们的代码转成浏览器可以直接执行的代码

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容