node.js的模块化介绍

1. 模块化介绍

1.1. 由于JavaScript不是一个模块化语言,存在两大缺陷:

a、文件中的代码会造成全局污染;

b、 依赖的加载顺序无法完全保证,例如jquery插件要在引入jquery后引入。

 

1.2.  Node中的模块化:

a、 文件天生就是一个私有的作用域

b、 文件与文件之间通过特定的规则进行交互(导入导出)

c、  程序最终由n个文件组成整个应用程序

d、 在每个模块内部,module代表当前模块,这个对象有一个属性exports,通过require函数加载这个模块,其实就是在加载某个模块,也就是该模块的module.exports接口。

 

2. Node中的模块分类

2.1. 核心模块https://nodejs.org/en/docs/  

就是node中的内置模块,例如fs,http等,其加载速度最快,因为已经被编译到node程序中了,每个模块都提供了一个唯一的核心标识名称,所以加载规则都一样

Var 变量名=require(‘核心模块名’)

 

1.2.  第三方模块

第三方模块就是由社区提供的模块(通常是npm),有将近35万个之多,通过在使用的时候都遵循以下三步:

a、 通过 npm 下载到项目中;

b、 通过 require 函数加载下载的第三方模块;

c、 查阅第三方模块的文档;

 

以marked为例(提供将markdown格式字符串转为HTML格式字符串的功能)

a、npm install marked

b、var marked = require(‘marked’)

c、console.log(marked(‘# hello world’))

d、输出结果为:<h1>hello world</h1>

 

1.3.  用户自定义模块

用户模块就是用户自己编写的文件模块,通常是一个文件或者多个文件组成。

例如以下简单的加减功能

在cal.js文件中

function add(x,y){

  return x+y;

};


function minus(x,y){

  return x-y;

}

module.exports.add=add;

module.exports.minus=minus;

在app.js文件中

var cal = require(‘./cal)

2.4.模块化特点总结

a、所有代码都运行在模块作用域,不会污染全局作用域

b、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存起来了,以后再加载,就直接读取缓存结果

c、模块加载的顺序,按照其在代码中出现的顺序

d、 module.exports 是模块的对外导出接口,其它文件加载该模块,实际上就是读取 module.exports

通过 require 函数加载别的模块,加载模块的过程实际上就是执行被加载模块中的代码,得到被加载模块的 module.exports 接口对象

 

3. exports和module.exports

为了方便,Node为每个模块提供了一个 exports 属性,指向 module.exports ,也就是说可以通过修改 exports 从而修改 module.exports

 

3.1. 如果需要向外只导出一个变量、例如一个函数、字符串、数字等,则必须通过为 module.exports 赋值才可以。

 

注意:为 exports 赋值是不管用的,因为每个模块最终对外到处的接口是 module.exports,而 exports 只是 module.exports 的一个引用,所以一旦给 exports 赋值,就切断了两者之间的引用关系,赋的值也就不管用了。

 

总结:如果希望向往导出多个接口成员,则可以使用 exports 添加属性成员方便的对外导出。

但是如果想要向外部提供一个单一的字符串、函数、数组等接口数据,则必须通过为 module.exports 赋值。(给 exports 赋值是不管用的)。

 

4. require 函数加载模块规则流程

require 函数接收的值被称作模块标识符,可能是一个核心模块标识名,也可能是一个第三方模块,也可能是一个相对路径形式的文件路径。在指定文件模块的时候,可以省略文件名后缀,当省略了文档名后缀之后,node 会以 .js、.node、.json 依次尝试补足。

 

下面是详细的加载规则:

4.1. 优先从缓存加载

4.2. 标识符分析

a、如果是核心模块,直接加载

b、如果是用户模块,即以 ./ 或者 ../ 开始的标识符或者绝对路径形式的模块,则直接加载

c、如果是第三方模块,则相对于当前模块找 node_modules 目录

d、找到 node_modules 目录之后,找与被加载模块同名的目录

e、如果找到,则找 package.json 文件,如果找到 package.json 文件,则找文件的 main 属性,如果找到 main 属性,则直接加载

f、如果没有 package.json 文件或者没有 main 属性或者 main 属性指定的文件模块不存在,则默认加载该目录中的 index.js、index.node、index.json

g、以上条件任何一个不成立,则直接进入上一级目录找 node_modules 目录,规则同上,直到找到当前文件模块所属磁盘根目录如果还找不到,则直接报错:can not find module xxx

 

posted @ 2017-03-16 19:37  尋壹米陽光  阅读(244)  评论(0编辑  收藏  举报