什么是模块?
为了让Node.js的文件可以相互调用,Node.js提供了一个模块系统。
模块是Node.js 应用程序的基本组成部分,文件和模块是一一对应的。换言之,一个 Node.js 文件就是一个模块,这个文件可能是JavaScript 代码、JSON 或者编译过的C/C++ 扩展。
Node中的模块划分:
Node中的模块分为:核心模块,文件模块,自定义模块(非核心模块)
在Node中引入模块:需经历3个步骤:
(1)路径解析
(2)文件定位
(3)编译执行
核心模块:在Node源代码编译过程中已经编译为二进制代码,在Node进程启动时,部分核心模块就加载到内存中,所以核心模块在引入时,文件定位和编译执行可以忽略, 加载速度最快。
文件模块:运行时动态加载,需完整的路径解析,文件定位,编译执行三步,速度慢于核心模块。
自定义模块速度慢的原因:在加载过程中,Node会逐个查找模块路径中的路径,直到找到目标文件为止,文件路径越深,耗时也越多。
二次加载:require()对模块进行二次加载时会采用缓存优先的加载方式。缓存加载的优先策略使得二次加载无需经历路径分析,文件定位,编译执行过程,提高了二次加载的效率。
Node.js中的模块加载机制:
1.绝对路径:
require('/home/liyabin/WebstormProjects/untitled/try.js');
2.相对路径:
require('./try.js');//如果写成require('try.js'),则会先加载node中的核心模块,后加载node-modules。
注意:如果不写文件后缀名,例如写成 require('./try'),则会涉及到文件查找机制:
1>首先按照加载的模块的文件名称进行查找,若未找到,则会在模块文件名称后面加上.js的后缀,进行查找。
2>如未找到,则会在模块文件名称后面加上.json的后缀,进行查找。
3>如还未找到,则会在模块文件名称后面加上.node的后缀,进行查找。
4>如果最后未找到,则会抛出一条错误消息。
综合上述,Node.js中的文件查找机制是:
文件名称 -> .js -> .json -> .node
模块对象: exports
在一个模块中通过var定义的变量,其作用域范围是当前模块,外部不能直接访问,若想一个模块能够访问另一个模块中定义的变量,有以下做法:
1>把变量作为global对象的一个属性(不推荐)
自定义模块:
global.a = 100;
文件模块:
require('/home/liyabin/WebstormProjects/untitled/try.js');
console.log(a);
在控制台输入指令:node 文件模块文件名称
输出结果为100
2>在模块作用域,有一个内置模块对象:exports。(单个输出变量)
自定义模块:
var num = 100;
var str = "Hello node";
exports.price = num;
exports.name = str;
exports.myFunction = function () {
console.log("Hello world");
};
文件模块:
var m = require('/home/liyabin/WebstormProjects/untitled/try.js');
console.log(m);
打印输出为:
{ price: 100, name: 'Hello node', myFunction: [Function] }
上面的写法会多次用到exports对象,比较麻烦。
3>通过module.exports对象把一个模块中的多个局部变量对外提供访问。(批量输出对象的属性和方法)
自定义模块:
var num = 100;
var str = "Hello node";
var f = function (){
console.log("Hello");
};
module.exports = {
price:num,
name:str,
myFunction:f
};
文件模块:
var m = require('/home/liyabin/WebstormProjects/untitled/try.js');
console.log(m);
ps: require()方法中的返回值就是自定义模块中的module.exports。
程序运行结果为:
{ price: 100, name: 'Hello node', myFunction: [Function: f] }
再讲一个module.exports和exports之间的关系的2个例子:
例一:
自定义模块:
exports.printHelloworld = ()=>{
console.log('Hello world');
}
文件模块:
var m = require('/home/liyabin/WebstormProjects/untitled/router.js');
m.printHelloworld();
运行node 文件模块:
在控制台输出 Hello World。
例二:
自定义模块:
function printHello(){
console.log("Hello");
}
module.exports = printHello;
文件模块:
var m = require('/home/liyabin/WebstormProjects/untitled/router.js');
m();
注意:
exports和module.exports对象其实指向相同的对象,不要破坏module.exports和exports之间的引用关系,