技术改变生活

Technology changes life,Life-long learning

Node.js(三)模块

在Node.js模块系统中,每个文件都被视为一个独立的模块

导出和引用模块


比如,新建一个people.js作为一个模块:
编辑代码:

这个js文件就是一个模块,这个模块用exports.方法名导出了sayMyname这个函数。
在执行代码之前,Node.js会先执行一个步骤:
Node.js把模块(每一个文件)封装在一个函数中(模块封装器)

模块封装器

在执行模块(文件)代码之前,Node.js会使用一个函数封装器来封装代码

通过在每个模块中添加了这样一层的包裹,Node.js实现了两>点:

  1. 使模块内的本地变量私有化,作用在模块范围内,而不是>暴露为全局对象。
  2. 提供了一些模块特定的变量:
    • exports:对于module.exports的更简短的引用形式
    • require:是一个函数,用于引入模块、 JSON、或本地文件。
    • module:对当前模块的引用, module.exports 用于指定一个模块所导出的内容,即可以通过 require() 访问的内容
    • __filename:当前模块已解析的绝对路径
    • __dirname:当前模块的目录名

exports是一个module.exports的更简短的引用形式,是一个对象,通过在此对象上指定额外的属性,可以将函数和对象添加到模块的根部。
在另一个模块(文件)中引用people模块,使用require语句来引用模块:

注意:使用console时,使用${变量}来包裹变量,有变量时,使用来作为输出语句的引号。
运行如下:

《Node.js(三)模块》

运行结果

exports 和 module.exports


exportsmodule.exports有什么不一样呢?通过上述介绍,可以知道exports 其实是module.exports 的引用,那么什么时候使用exports,什么时候使用module.exports 呢?
exports变量在模块内的作用域中是可用的,且在模块执行之前赋值给module.exports
故此,module.exports.f = ... 可以快捷地写成exports.f = ...,但是当给它赋值之后,它将不再绑定到module.exports,即,当你要使用赋值语句时,就不可再使用exports = ...,而要使用module.exports = ...

通过require()的实现来说明他们之间的关系:

综上,可以知道使用exportsmodule.exports的场景:

  1. 当希望模块导出一个空的默认对象,以及暴露一些外部可以通过这个对象访问的api或者变量时,使用exports

  1. 当希望模块导出一个变量或函数时,外部直接访问这个变量和函数,使用module.exports

想要传参数到模块中动态配置的方法:
使用module.exports导出一个工厂函数,这个函数可以传入参数,在这个函数中,模块内就可以使用参数进行逻辑操作,从而达到动态配置的效果,如
设置一个模块,可以计算汇率,设置汇率会动态配置的参数:

在外部动态配置汇率,结构出我们要使用的函数:

访问主模块

主模块,即当前模块是不是直接运行的模块(文件)。
当Node.js直接运行一个文件时,require.main会被设置为其module,如果要判断一个文件是不是被直接运行,通过以下语句判断:

如果是通过node xxx.js运行,为true;
如果是通过require运行,为false。
要获取当前程序的入口点,可以通过以下代码获取:

核心模块

Node.js有一些模块是核心模块,定义在lib/目录下,require()会优先加载核心模块,即使有模块与核心模块重名,也会先加载内置的模块。

require()查找目录

require中传入的参数有以下几种情况

  • 以 ‘/’ 为前缀的模块是文件的绝对路径。 例如, require(‘/home/marco/foo.js’) 会加载 /home/marco/foo.js 文件。
  • 以 ‘./’ 为前缀的模块是相对于调用 require() 的文件的。 也就是说, circle.js 必须和 foo.js 在同一目录下以便于 require(‘./circle’) 找到它。
  • 当没有以 ‘/’、 ‘./’ 或 ‘../’ 开头来表示文件时,这个模块必须是一个核心模块或加载自 node_modules 目录。
    *如果给定的路径不存在,则 require() 会抛出一个 code 属性为 'MODULE_NOT_FOUND'Error
    在一个项目中设定入口文件时,通常是在根目录下创建一个package.json文件,并定一个main模块,如:

如果这是在 ./some-library 目录中,则 require(‘./some-library’) 会试图加载 ./some-library/lib/some-library.js。
如果目录中没有package.json文件,则Node.js会试图加载目录中的index.js或者index.node。

详解module对象

每个模块中都有一个module对象,表示当前模块的对象的引用。里面有一些关于本模块(文件)的信息。module对象是每个模块本地的。
在文件中输出module:

可以得到如下结果:

《Node.js(三)模块》

module构成

组成解析:

  • id:<string>模块的标识符,通常是完全解析后的文件名
  • exports:<Object>对象,可用于导出变量或函数等
  • parent:* <Object>模块对象,最先应用该模块的模块
  • filename:<string>完全解析后的文件名
  • loaded:<boolean>模块是否加载完成,或者正在加载中
  • children:<Array>被该模块引用的模块对象数组
  • paths:<string[]>模块的搜索路径,是一个数组
  • require(id):返回已解析的模块的module.exports

npm


npm是Node.js的包管理器,通常在安装Node.js的时候一起安装了。
查看npm的版本

原文始发于:Node.js(三)模块

点赞