美文网首页
Node.js(三)模块

Node.js(三)模块

作者: 偶余杭 | 来源:发表于2019-03-02 20:02 被阅读0次

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

导出和引用模块


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

exports.sayMyName = (name) => {return '我的名字是'+name};

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

模块封装器

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

(function(exports, require, module, __filename, __dirname) {
// 模块的代码实际上在这里
});

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

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

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

const people = require('./people.js')
console.log(`这位先生开始介绍自己,他说道:${people.sayMyName("Jack")}`)

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


运行结果

exports 和 module.exports


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

module.exports.hello = true;//从模块的引用中导出
exports.hello = true;//从模块的引用中导出
module.exports = exports = function Contructor(){};//导出模块
//module.exports被赋值时,也会重新赋值exports
exports = { hello: false };  // 不导出,仅在模块中可用。
//此时,exports 不与 module.exports绑定了。

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

function require(/* ... */) {
  const module = { exports: {} };
  ((module, exports) => {
    // 模块代码在这。在这个例子中,定义了一个函数。
    function someFunc() {}
    exports = someFunc;
    // exports被赋值了,此时,exports 不再是一个 module.exports 的快捷方式,
    // 且这个模块依然导出一个空的默认对象。
    module.exports = someFunc;
    // module.exports被赋值了,此时,该模块导出 someFunc,而不是默认对象。
  })(module, module.exports);
  return module.exports;
}

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

  1. 当希望模块导出一个空的默认对象,以及暴露一些外部可以通过这个对象访问的api或者变量时,使用exports
//模块中导出
exports.func = ...
exports.a = ...
//外界访问
const moduleName = require('module.js');//获取默认对象
moduleName.func();//访问对象中挂载暴露的函数
console.log(moduleName.a);
  1. 当希望模块导出一个变量或函数时,外部直接访问这个变量和函数,使用module.exports
//模块中导出
module.exports = function(){}
//外界访问
const moduleName = require('module.js');//获取默认对象
moduleName()

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

let rate;
function rmbToDollar(rmb){
    return rmb/rate;
}

module.exports = function(r){
    rate = r
    return {rmbToDollar} 
}

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

const {rmbToDollar} = require('./currency')(6)
console.log(rmbToDollar(10))

访问主模块

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

require.main === module

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

require.main._filename

核心模块

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模块,如:
{ "name" : "some-library",
  "main" : "./lib/some-library.js" }

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

详解module对象

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

console.log(module)

可以得到如下结果:


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的版本

npm -v

相关文章

  • 深入解析node.js的模块加载机制

    在node.js中,模块使用CommonJS规范,一个文件是一个模块 node.js中的模块可分为三类 内部模块 ...

  • 浅析node.js的模块加载逻辑

    module 在node.js中,模块使用CommonJS规范,一个文件是一个模块 node.js中的模块可分为三...

  • 2.模块/包与CommonJS

    1.Node.js模块 内置的Node.js模块 2.第三方的Node.js模块当需要安装第三方的包时,可以在如下...

  • 关于node.js一些模块的记录「FS模块」

    目录 Node.JS教程 FS模块 Path模块 FS模块 Path模块 Node.js path 模块提供了一些...

  • 5-创建及发布node.js模块

    创建node.js模块node.js模块是可以发布在npm上的package,当你要创建一个node.js模块时,...

  • npm与包

    包 什么是包 Node.js 中的第三方模块又叫做包。 包的来源 不同于 Node.js 中的内置模块与自定义模块...

  • Node.js HTTP模块

    内置HTTP模块 Node.js 中有 HTTP 这个内置模块,HTTP 模块允许 Node.js 通过超文本传输...

  • Node.js模块

    Node.js 模块和 Node.js 包介绍。 一、Node.js模块 每一个Node.js都是一个Node.j...

  • Node.js与内置模块

    目录: 认识Node.js fs文件系统模块 path路径模块 http模块 认识Node.js 为啥JavaSc...

  • Node学习(6)--模块系统

    Node.js模块系统 为了让Node.js的文件可以相互调用,Node.js提供了一个简单的模块系统。模块是No...

网友评论

      本文标题:Node.js(三)模块

      本文链接:https://www.haomeiwen.com/subject/fbtyuqtx.html