Node.js模块加载

编程入门 行业动态 更新时间:2024-10-23 19:26:19

Node.js<a href=https://www.elefans.com/category/jswz/34/1771428.html style=模块加载"/>

Node.js模块加载

JS 是世界上使用频率最高的语言之一,JS 的核心是在 Netscape 公司大行其道的岁月里创建的,当时正处于浏览器白热化时期,JS 作为打击 Microsoft 的利器匆忙上马。它并没有发展得十分成熟就被发布,这意味着不可避免地带有一些糟糕的特性。虽然开发时间不长,但 JS 被赋予一些强大的特性。不过“脚本间共享全局命名空间”这一特性却不在其中。

一旦 JS 代码被载入页面,就会被添加进全局命名空间,全局命名空间是被所有已载入的脚本所共享的通用地址空间,这样会导致安全性问题、命名冲突以及一些难以跟踪和解决的一般性错误。

值得庆幸的是 Node 作为服务端的 JS 制定了一些规范,并实现了 CommonJS 模块标准。在这个标准中,每个模块都拥有一个上下文,将该模块和其他模块隔离开来,这意味着模块不会污染全局作用域,因为根本就没有全局作用域,并且也不会对其他模块造成干扰。

Node是如何加载模块的?

在 Node 可用文件路径也可用名称来引用模块,除非是核心模块,否则用名称引用的模块最终都会被映射为一个文件路径。Node 核心模块将一些核心函数暴露给程序员,它们在 Node 进程启动时会被预先载入。其他模块包括使用 NPM 安装的第三方模块,以及用户自己创建的本地模块。

不管什么类型的模块,在被导入当前脚本后,程序员都可以使用其对外暴露一组公共 API 。不管使用什么模块,你都可以使用 require() 载入它。

// 导入一个核心模块或由NPM安装的模块
// require() 会返回一个对象,该对象表示模块对外暴露的JS API。
// 根据模块不同,该对象可能是任意的JS值,可是一个函数,也可是一个具有若干属性的对象,属性可能是函数、数组或其它任何类型的JS对象。
var module = require('module_name');

导出模块

Node 中 CommonJS 模块系统是文件之间共享对象或函数的唯一方式,对于足够复杂的应用,应将一些类、对象、函数划分成定义良好的可重用模块,模块值对外暴露你指定的内容。

Node 中文件和模块是一一对应的,Node 可导出复杂的对象,module.exports 被初始化成一个空对象,可为空对象附加上任意想要导出的属性。

$ vim circle.js
function Circle(r){function square(){return Math.pow(r,2);}function area(){return Math.PI*square();}return {area:area};
}
// 定义模块导出的内容
// module是个变量表示当前模块自身
// module.exports 表示模块向需要它的脚本所导出的对象,可是任意对象。
// 导出Circle类的构造函数,用户可使用该函数来创建具备完整功能的Circle实例。
module.exports = Circle;

可设计模块让其导出一组函数或常量

$ vim module.js
function printA(){console.log('a');
}
function printB(){console.log('b');
}
function printC(){console.log('c');
}module.exports.printA = printA;
module.exports.printB = printB;
module.exports.printC = printC;module.expots.pi = Math.PI;

使用模块的客户端脚本

$ vim test.js
var module = require('./module');
module.printA();
module.printB();
console.log(module.pi);

加载模块

可使用 require() 加载模块,在代码中调用 require() 不会改变全局命名空间的状态,因为在 Node 中根本就没有全局命名空间这个概念。若模块存在并没有任何语法或初始化错误,调用 require() 就会返回这个模块对象,然后就可以将这个对象赋值给任意一个局部变量。

引用模块的方式会决定模块的类型

  • 核心模块
  • NPM 安装的第三方模块
  • 本地模块

加载核心模块

核心模块是指 NPM 中以二进制形式发布的模块,核心模块只能通过模块名引用,而不能通过文件路径引用。即使已经存在一个与其同名的第三方模块,也会优先加载核心模块。

// 加载http核心模块,返回http模块对象,该对象实现由Node API文件描述的 HTTP API.
var http = require('http');

加载文件模块

可通过提供绝对路径或相对路径从文件系统中加载非核心模块,可省略文件扩展名 .js 。若没找到此文件,Node会在文件名上添加 .js 扩展名再次查找路径。

// 以绝对路径从文件系统中加载非核心模块
var myModule = require('/home/user/modules/my_module');// 基于当前文件的相对路径
var myModule = require('./lib/my_module');
var myModule = require('../modules/my_module');// 模块扩展名可省略
var myModule = require('./my_module.js');

加载文件夹模块

// 可使用文件夹路径加载模块,Node会在指定文件夹下查找模块。
// Node假定该文件夹是一个包,并试图查找包定义。包定义包含在名为 package.json 文件中。
// 若文件夹中不存在包定义文件 package.json, 那么包入口点会假定为默认值 index.js。
// 若文件夹中存在 package.json,那么Node会尝试解析该文件并查找 main 属性,将 main 属性作为入口点的相对路径。
var myModule = require('./modules');// Node 将会在路径 ./modules/index.js 下查找文件

从 node_modules 文件夹加载

若一个模块名即不是相对路径也不是核心模块,Node 会尝试在当前目录下的 node_modules 文件夹中查找该模块。

// Node 会尝试查找文件 ./node_modules/module.js
// 若没有找到该文件,Node会继续在父文件夹 ../node_modules/module.js 中查找
// 若没有找到该文件,Node会继续查找上级父文件夹,这个过程一直持续到达根目录或找到所需的模块为止。
var myModule = require('module.js');

可利用此特性管理 node_modules 目录中的内容,不过最好还是让 NPM 来管理模块。本地模块 node_modules 是 NPM 安装模块的默认位置,此项功能将Node和NPM关联到一起。

缓存模块

模块在首次加载时会被缓存起来,这意味着若模块名能被解析为相同的文件名,那么每次调用 require('module') 都会确切地返回同一模块。

$ vim my_module.js
console.log('module my_module initializing...');// 模块初始化过程只执行了一次,当构建自定义模块时,若模块在初始化时可能会产生副作用。
module.exports = function(){console.log('hi');
};console.log('my_module initialized')

模块初始化过程只执行了一次

var m1 = require('./my_module.js');
var m2 = require('./my_module');

总结

Node取消了JS默认的全局命名空间,而用CommonJS模块系统取而代之,这样可更好地组织代码,也因此避免了了一些安全问题和错误。
使用 require() 从文件或文件夹加载核心模块、第三方模块、自定义模块。可使用相对或绝对路径加载非核心模块。若将模块放入 node_modules 文件夹或使用 NPM 安装模块,也可使用模块名加载。
可编写JS文件导出标识模块API的对象,以此创建自定义模块。

更多推荐

Node.js模块加载

本文发布于:2024-03-08 21:16:20,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1722400.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:模块   加载   Node   js

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!