NodeJS学习笔记之模块的简介

  

<强> node . js模块系统

  

节点。js有一个简单的模块加载系统。在node . js中,文件和模块是一一对应的(每个文件被视为单独的模块)。

  

例如,考虑下面这个名为foo。js的文件:

        const圆=要求('/circle.js。');   控制台。日志(半径的圆的面积4 $ {circle.area (4)}”);   之前      

在第一行,foo。js加载与foo。js同一目录的模块圆。js .

  

循环。js的内容如下:

        constπ=Math.PI;      出口。面积=(r)=比;π* * r;      出口。周长=(r)=比;2 *π* r;      之前      

模块圆。js导出了函数<代码>区域()和<代码>周长()>   

模块内部的变量一定是私有的,因为模块被节点。js包裹在一个函数中(参见下面的模块包装器)。在这个例子中,变量π对于圆。js来说是私有变量。

  

如果你希望模块导出的是一个函数(如构造函数),或者是要导出完整的对象,而不是一次创建一个属性,则需要将其分配给<代码>模块。出口>   

在下面的酒吧。js中,使用了广场<代码> 模块,它导出一个构造函数:

        const平方=要求('/square.js。');   var mySquare=广场(2);   控制台。日志(“我广场的面积是$ {mySquare.area ()}”);   之前      

在广场。js模块中定义一个广场方法:

        模块。出口=(宽度)=比;{   返回{   面积:()=比;宽度*宽度;   };   }   之前      

此外,模块系统在要求(“模块”)模块中实现。

  

<强>“主要”模块

  

当某个模块直接从节点。js运行时,它会将需要。主要设置该模块。你可以通过这个来测试这个模块是被直接运行的还是被需要的。

  

<代码>。主要模块===
  

  

就拿文件foo。js来说,如果运行节点foo。js这个属性就是真的。运行要求(“。/foo.js”)就是假的。

  

因为模块提供了一个文件名(通常相当于__filename),因此可以通过检查require.main。文件名来获取当前应用程序的入口点。

  

<强>包管理器的一些提示

  

节点。js的需要()函数支持一些合理的目录结构。它让软件包管理器程序(如dpkg, rpm和npm)可以从node . js模块中直接去构建本地的包而不需要修改。

  

下面我们给出一个可以正常工作的建议目录结构:

  

假设我们希望在/usr/lib/node//& lt; some-version>中的文件夹来指定版本的包。

  

此外,包还可以相互依赖。比如你想安装foo包,而这个包有可能需要安装指定版本包的酒吧。酒吧而包也很有可能依赖其他的包,并且在某些特殊情况下,这些依赖包甚至可能会产生循环依赖。

  

由于节点。js会查找加载的所有模块的realpath(即解析软链),然后再去node_modules文件夹中查找依赖的包,因此使用以下方案可以非常简单地解决此问题:

  

/usr/lib/节点/foo/1.2.3/-包含foo包,版本是1.2.3

  

/usr/lib/节点/酒吧/4.3.2/-包含foo所依赖的酒吧包

  

/usr/lib/节点/foo/1.2.3/node_modules/bar -软链到/usr/lib/node/bar/4.3.2/

  

/usr/lib/节点/酒吧/4.3.2/node_modules/* -软链到酒吧的依赖

  

因此,即使遇到循环依赖,或者是依赖冲突,每个模块都能加载到并使用自己所依赖指定版本的包。

  

当foo包中需要(“酒吧”)时,它就可以软链到指定版本的/usr/lib/node/foo/1.2.3/node_modules/酒吧。然后,当酒吧包中的代码调用要求(“quux”)时,它同样也可以软链到指定版本的/usr/lib/node/bar/4.3.2/node_modules/quux。

  

模块加载的全过程(重点、下面写的伪代码流程一定要记住)

  

要获取在调用需要()将被加载的确切文件名,请使用require.resolve()函数。

  

以下是模块加载的全过程以及要求。解决的解析过程:

     //加载X模块   需要Y (X)从模块路径   1. 如果X是一个核心模块。   答:返回的核心模块   b。停止   2. 如果X开头”。/被颉?被颉? ./?   一。LOAD_AS_FILE (Y + X)   b。LOAD_AS_DIRECTORY (Y + X)   3.LOAD_NODE_MODULES (X,目录名(Y))   4. 把“未找到”//加载X文件//加载过程:X→X。js→X。json→X.node   LOAD_AS_FILE (X)   1. 如果[X]是一个文件,加载[X]作为JavaScript文本。停止   2. 如果[X。js是一个文件,加载[X。js JavaScript文本。停止   3.如果[X。json是一个文件,加载[X。json)作为JavaScript文本。停止   4. 如果[X。节点是一个文件,加载[X。作为JavaScript文本节点)。停止//加载入口文件//加载过程:X→X/索引。js→X/索引。json→X/index.node   LOAD_INDEX (X)   1. 如果(X/索引。js是一个文件,加载(X/索引。js JavaScript文本。停止   2. 如果(X/索引。json是一个文件,加载(X/索引。json)作为JavaScript文本。停止   3.如果(X/索引。节点)如果文件、负载(X/索引。作为JavaScript文本节点)。停止//加载文件夹   LOAD_AS_DIRECTORY (X)   1. 如果(X/包。json是一个文件。   解析(X/包。json),寻找“主要”字段   b让M=X + (json主要字段)   c。LOAD_AS_FILE (M)   d。LOAD_INDEX (M)   2. LOAD_INDEX (X)//加载节点模块   LOAD_NODE_MODULES (X,开始)   1. 让DIRS=NODE_MODULES_PATHS(开始)   2. 为每个DIR DIRS;   一。LOAD_AS_FILE (DIR/X)   b。LOAD_AS_DIRECTORY (DIR/X)//列出所有可能的node_modules路径   NODE_MODULES_PATHS(开始)   1. 让部分=路径分裂(开始);   2. 让我=- 1的零件数   3.让DIRS=[]   4. 当我在0   如果部分。[我]=皀ode_modules”继续   b . DIR=路径加入(部分[0…我)+“node_modules”)   c . DIRS=DIRS + DIR   d .让我=1   5. 返回DIRS      

NodeJS学习笔记之模块的简介