老阿姐 發表於 2022-9-5 08:25:00

Node.js学习笔记(二)——Node.js模块化、文件读写、环境变量

<h1>一、Node.js模块化</h1>
<h2>1.0、变量作用域</h2>
<p>(1)、在浏览器端使用var或不使用关键字定义的变量属于全局作用域,也就是可以使用window对象访问。</p>
<div class="cnblogs_code">
<pre>    &lt;script&gt;
      <span style="color: rgba(0, 0, 255, 1)">var</span> a = 100<span style="color: rgba(0, 0, 0, 1)">;

      (</span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> () {
      b </span>= 200<span style="color: rgba(0, 0, 0, 1)">;
      })();

      console.log(window.a, a);
      console.log(window.b, b);
    </span>&lt;/script&gt;</pre>
</div>
<p>结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220906151310875-176035144.png" alt="" width="369" height="168" loading="lazy"></p>
<p>(2)、在Node.js中没有window对象</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220906151438387-1532322315.png" alt="" width="563" height="332" loading="lazy"></p>
<p>&nbsp;(3)、在Node.js的交互环境下,定义的变量属于global,global是类似浏览器端的window对象</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220906151601423-1607815051.png" alt="" width="398" height="241" loading="lazy"></p>
<p>&nbsp;(4)、在模块中(文件中)有global对象,使用关键字var,let,const定义的成员不属于global对象,仅在当前模块中有效,而不使用关键字定义的对象属于global对象。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> a=100<span style="color: rgba(0, 0, 0, 1)">;
b</span>=200<span style="color: rgba(0, 0, 0, 1)">;
let c</span>=300<span style="color: rgba(0, 0, 0, 1)">;
const d</span>=400<span style="color: rgba(0, 0, 0, 1)">;
console.log(global);
console.log(global.a);
console.log(global.b);
console.log(global.c);
console.log(global.d);</span></pre>
</div>
<p>终端输出:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220906152251637-568269443.png" alt="" width="425" height="272" loading="lazy"></p>
<h2>1.1、模块概要</h2>
<p>早期的javascript版本没有块级作用域、没有类、没有包、也没有模块,这样会带来一些问题,如复用、依赖、冲突、代码组织混乱等,随着前端的膨胀,模块化显得非常迫切。</p>
<p><img src="https://img2018.cnblogs.com/blog/63651/201811/63651-20181128162655341-2033851678.png" alt=""></p>
<p>前端模块化规范如下:</p>
<p><img src="https://img2018.cnblogs.com/blog/63651/201812/63651-20181204155136389-1035561659.png" alt=""></p>
<p>常见的的JavaScript模块规范有:CommonJS、AMD、CMD、UMD、原生模块化。</p>
<p>虽然我们学习过ES6的模块化但是ES6与NodeJS使用不同的模块化规范,单独学习NodeJS的模块化非常有必要。</p>
<p>模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换 的单元。</p>
<p>JavaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。</p>
<p><span style="color: rgba(0, 0, 255, 1)">模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块</span>。</p>
<p>模块化开发的四点好处:</p>
<p><span style="color: rgba(0, 0, 255, 1)">  (1)、 避免变量污染,命名冲突</span></p>
<p><span style="color: rgba(0, 0, 255, 1)">  (2)、提高代码复用率</span></p>
<p><span style="color: rgba(0, 0, 255, 1)">  (3)、提高了可维护性</span></p>
<p><span style="color: rgba(0, 0, 255, 1)">  (4)、方便依赖关系管理</span></p>
<p>nodejs中根据模块的来源不同,将模块分为了3大类,分别是:</p>
<ul>
<li>内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)</li>
<li>自定义模块&nbsp;(用户创建的每个 .js文件,都是自定义模块)</li>
<li>第三方模块&nbsp;(由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)</li>
</ul>
<p><span style="color: rgba(255, 0, 0, 1)">模块作用域。</span></p>
<p>和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。</p>
<p>模块作用域的好处:防止了全局变量污染的问题</p>
<h2>1.2、CommonJS</h2>
<p>CommonJS就是一个JavaScript模块化的规范,该规范最初是用在服务器端NodeJS中,前端的webpack也是对CommonJS原生支持的。</p>
<p>根据这个规范</p>
<p><span style="color: rgba(255, 0, 0, 1)">(1)、每一个文件就是一个模块</span>,<span style="color: rgba(255, 0, 0, 1)">其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。</span></p>
<p><span style="color: rgba(255, 0, 0, 1)">(2)、导入自定义的模块时路径需要以./或../开始,同一路径下也不能省略。</span></p>
<p><span style="color: rgba(255, 0, 0, 1)">(3)、如果反复多次require模块,只加载一次。</span></p>
<p><span style="color: rgba(255, 0, 0, 1)">(4)、require引入模块时,后缀名.js可以省略</span></p>
<p><span style="color: rgba(255, 0, 0, 1)">(5)、每个模块文件都是一个独立的函数级作用域,在其它模块中不能直接访问</span></p>
<p><span style="color: rgba(0, 0, 0, 1)">m1.js:</span></p>
<div class="cnblogs_code">
<pre>console.log("这是模块m1"<span style="color: rgba(0, 0, 0, 1)">);
let a</span>=100<span style="color: rgba(0, 0, 0, 1)">;
b</span>=200;</pre>
</div>
<p>m2.js</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> m11=require("./m1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(a);
console.log(b);</span></pre>
</div>
<p>结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907093355159-1001178021.png" alt="" width="446" height="124" loading="lazy"></p>
<p>&nbsp;从上面的示例可以看出a在模块2中是访问不到的,模块其实就是一个封闭的函数:</p>
<p>m1.js的代码如下:</p>
<div class="cnblogs_code">
<pre>console.log("这是模块m1"<span style="color: rgba(0, 0, 0, 1)">);
let a</span>=100<span style="color: rgba(0, 0, 0, 1)">;
b</span>=200<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">输出当前函数</span>
console.log(arguments.callee+"");</pre>
</div>
<p>实际输出结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907093805366-310578169.png" alt="" width="532" height="212" loading="lazy"></p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (exports, require, module, __filename, __dirname) {
console.log(</span>"这是模块m1"<span style="color: rgba(0, 0, 0, 1)">);
let a</span>=100<span style="color: rgba(0, 0, 0, 1)">;
b</span>=200<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">输出当前函数</span>
console.log(arguments.callee+""<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p><span style="color: rgba(255, 0, 0, 1)">(6)、每个模块中都包含如下5个对象:</span></p>
<p>exports:导出对象,默认为{}</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907094235495-602848893.png" alt="" width="608" height="382" loading="lazy"></p>
<p>require:导入函数,使用该函数可以实现模块的依赖</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907094307006-1979159960.png" alt="" width="558" height="321" loading="lazy"></p>
<p>module:模块信息,用于记录当前模块的所有信息</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907094439080-1427381073.png" alt="" width="515" height="526" loading="lazy"></p>
<p>__filename:当前模块的文件全路径,含文件名</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907094534975-2015594813.png" alt="" width="540" height="206" loading="lazy"></p>
<p>__dirname:当前模块的文件路径不含文件名</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907094610790-1045387680.png" alt="" width="429" height="173" loading="lazy"></p>
<p><span style="color: rgba(255, 0, 0, 1)">(7)、使用exports或module.exports对象可以将当前模块中需要导出的内容暴露出去。</span></p>
<p>m1.js</p>
<div class="cnblogs_code">
<pre>let a=100<span style="color: rgba(0, 0, 0, 1)">;
let b</span>=()=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> 200<span style="color: rgba(0, 0, 0, 1)">;
};

exports.a</span>=<span style="color: rgba(0, 0, 0, 1)">a;
exports.b</span>=b;</pre>
</div>
<p>m2.js</p>
<div class="cnblogs_code">
<pre>const m1=require("./m1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(m1);
console.log(m1.a);
console.log(m1.b());</span></pre>
</div>
<p>结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907095249342-716966071.png" alt="" width="505" height="129" loading="lazy"></p>
<p><span style="color: rgba(255, 0, 0, 1)">(8)、导入模块内容可以结合解构语法</span></p>
<p>m1.js</p>
<div class="cnblogs_code">
<pre>exports.a=100<span style="color: rgba(0, 0, 0, 1)">;
exports.b</span>=<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(){
    </span><span style="color: rgba(0, 0, 255, 1)">return</span> 200<span style="color: rgba(0, 0, 0, 1)">;
};</span></pre>
</div>
<p>m2.js</p>
<div class="cnblogs_code">
<pre>const {a,b:fun}=require("./m1"<span style="color: rgba(0, 0, 0, 1)">);
console.log(a);
console.log(fun());</span></pre>
</div>
<p>结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907113327105-49286396.png" alt="" width="441" height="92" loading="lazy"></p>
<h2>1.3、NodeJS中使用CommonJS模块管理</h2>
<p>CommonJS的核心思想就是通过&nbsp;require 方法来同步加载所要依赖的其他模块,然后通过&nbsp;exports 或者 module.exports 来导出需要暴露的接口。</p>
<p>CommonJS API编写应用程序,然后这些应用可以运行在不同的JavaScript解释器和不同的主机环境中。</p>
<p>2009年,美国程序员Ryan Dahl创造了node.js项目,将javascript语言用于服务器端编程。这标志"Javascript模块化编程"正式诞生。因为老实说,在浏览器环境下,以前没有模块也不是特别大的问题,毕竟网页程序的复杂性有限;但是在服务器端,一定要有模块,与操作系统和其他应用程序互动,否则根本没法编程。NodeJS是CommonJS规范的实现,webpack 也是以CommonJS的形式来书写。</p>
<div class="cnblogs_code">
<pre><span>CommonJS定义的模块分为:{模块引用(require)} {模块定义(exports)} {模块标识(module)}
//require()用来引入外部模块;
//exports对象用于导出当前模块的方法或变量,唯一的导出口;
//module对象就代表模块本身。</span></pre>
</div>
<p>Nodejs的模块是基于CommonJS规范实现的,通过转换也可以运行在浏览器端。</p>
<p><img src="https://img2018.cnblogs.com/blog/63651/201811/63651-20181130104503977-688996773.png" alt=""></p>
<p>特点:</p>
<div>1、所有代码都运行在模块作用域,不会污染全局作用域。</div>
<div>2、模块可以多次加载,但是只会在第一次加载时运行一次,然后运行结果就被缓存了,以后再加载,就直接读取缓存结果。要想让模块再次运行,必须清除缓存。</div>
<div>3、模块加载的顺序,按照其在代码中出现的顺序。</div>
<h3>1.3.1、模块定义</h3>
<p>根据commonJS规范,<span style="color: rgba(255, 0, 0, 1)">一个单独的文件是一个模块</span>,<span style="color: rgba(255, 0, 0, 1)">每一个模块都是一个单独的作用域</span>,也就是说,<span style="color: rgba(255, 0, 0, 1)">在该模块内部定义的变量,无法被其他模块读取,除非为global对象的属性</span>。</p>
<p>模块拥有像函数一样的函数级作用域:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202206/63651-20220628093556381-1988431083.png" alt="" loading="lazy"></p>
<ol>
<li>每个模块内部,module变量代表当前模块</li>
<li>module变量是一个对象,它的exports属性(即module.exports)是对外的接口</li>
<li>加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块。</li>
</ol>
<p>模块只有一个出口,module.exports对象,我们需要把模块希望输出的内容放入该对象。</p>
<p>mathLib.js模块定义</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> message="Hello CommonJS!"<span style="color: rgba(0, 0, 0, 1)">;

module.exports.message</span>=<span style="color: rgba(0, 0, 0, 1)">message;
module.exports.add</span>=(m,n)=&gt;console.log(m+n);</pre>
</div>
<p>在 Node.js 中,创建一个模块非常简单,如下我们创建一个 'main.js' 文件,代码如下:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> hello = require('./hello'<span style="color: rgba(0, 0, 0, 1)">);
hello.world();</span></pre>
</div>
<p>以上实例中,代码 require('./hello') 引入了当前目录下的hello.js文件(./ 为当前目录,node.js默认后缀为js)。</p>
<p>Node.js 提供了exports 和 require 两个对象,<span style="color: rgba(255, 0, 0, 1)">其中 exports 是模块公开的接口,require 用于从外部获取一个模块的接口</span>,即所获取模块的 exports 对象。</p>
<p>接下来我们就来创建hello.js文件,代码如下:</p>
<div class="cnblogs_code">
<pre>exports.world = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
console.log(</span>'Hello World'<span style="color: rgba(0, 0, 0, 1)">);
}</span></pre>
</div>
<p>在以上示例中,hello.js 通过 exports 对象把 world 作为模块的访 问接口,在 main.js 中通过 require('./hello') 加载这个模块,然后就可以直接访 问main.js 中 exports 对象的成员函数了。</p>
<p>有时候我们只是想把一个对象封装到模块中,格式如下:</p>
<div class="cnblogs_code">
<pre>module.exports = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> ...</span>
}</pre>
</div>
<p>例如:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">hello.js </span>
<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> Hello() {
    varname;
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.setName = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(thyName) {
      name </span>=<span style="color: rgba(0, 0, 0, 1)"> thyName;
    };
    </span><span style="color: rgba(0, 0, 255, 1)">this</span>.sayHello = <span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">() {
      console.log(</span>'Hello ' +<span style="color: rgba(0, 0, 0, 1)"> name);
    };
};
module.exports </span>= Hello;</pre>
</div>
<p>这样就可以直接获得这个对象了:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">main.js </span>
<span style="color: rgba(0, 0, 255, 1)">var</span> Hello = require('./hello'<span style="color: rgba(0, 0, 0, 1)">);
hello </span>= <span style="color: rgba(0, 0, 255, 1)">new</span><span style="color: rgba(0, 0, 0, 1)"> Hello();
hello.setName(</span>'BYVoid'<span style="color: rgba(0, 0, 0, 1)">);
hello.sayHello();</span></pre>
</div>
<p>模块接口的唯一变化是使用 module.exports = Hello 代替了exports.world = function(){}。 在外部引用该模块时,其接口对象就是要输出的 Hello 对象本身,而不是原先的 exports。</p>
<h3>1.3.2、模块依赖</h3>
<p>加载模块用require方法,该方法读取一个文件并且执行,返回文件内部的module.exports对象。</p>
<p>在用require加载自定义模块期间,可以省略.js这个后缀名。</p>
<p>myApp.js 模块依赖</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> math=require('./mathLib'<span style="color: rgba(0, 0, 0, 1)">);
console.log(math.message);
math.add(</span>333,888);</pre>
</div>
<p>3、测试运行</p>
<p>安装好node.JS</p>
<p>打开控制台,可以使用cmd命令,也可以直接在开发工具中访问</p>
<p><img src="https://img2018.cnblogs.com/blog/63651/201811/63651-20181130142600744-662580048.png" alt=""></p>
<p>运行</p>
<p><img src="https://img2018.cnblogs.com/blog/63651/201811/63651-20181130142621586-1528715093.png" alt=""></p>
<h3>1.3.3、内置模块加载</h3>
<p>也许你已经注意到,我们已经在代码中使用了模块了。像这样:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> http = require("http"<span style="color: rgba(0, 0, 0, 1)">);

...

http.createServer(...);</span></pre>
</div>
<p>Node.js中自带了一个叫做"http"的模块,我们在我们的代码中请求它并把返回值赋给一个本地变量。</p>
<p>这把我们的本地变量变成了一个拥有所有 http 模块所提供的公共方法的对象。</p>
<p>Node.js 的 require方法中的文件查找策略如下:</p>
<p>由于Node.js中存在4类模块(原生模块和3种文件模块),尽管require方法极其简单,但是内部的加载却是十分复杂的,其加载优先级也各自不同。如下图所示:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202206/63651-20220628095254493-2140511914.png" alt="" loading="lazy"></p>
<p id="从文件模块缓存中加载"><strong>从文件模块缓存中加载</strong></p>
<p>尽管原生模块与文件模块的优先级不同,但是都不会优先于从文件模块的缓存中加载已经存在的模块。</p>
<p><strong>从原生模块加载</strong></p>
<p>原生模块的优先级仅次于文件模块缓存的优先级。require方法在解析文件名之后,优先检查模块是否在原生模块列表中。以http模块为例,尽管在目录下存在一个http/http.js/http.node/http.json文件,require("http")都不会从这些文件中加载,而是从原生模块中加载。</p>
<p>原生模块也有一个缓存区,同样也是优先从缓存区加载。如果缓存区没有被加载过,则调用原生模块的加载方式进行加载和执行。</p>
<p id="从文件加载"><strong>从文件加载</strong></p>
<p>当文件模块缓存中不存在,而且不是原生模块的时候,Node.js会解析require方法传入的参数,并从文件系统中加载实际的文件,加载过程中的包装和编译细节在前一节中已经介绍过,这里我们将详细描述查找文件模块的过程,其中,也有一些细节值得知晓。</p>
<p>require方法接受以下几种参数的传递:</p>
<ul>
<li>http、fs、path等,原生模块。</li>
<li>./mod或../mod,相对路径的文件模块。</li>
<li>/pathtomodule/mod,绝对路径的文件模块。</li>
<li>mod,非原生模块的文件模块。</li>
</ul>
<p>node_modules文件夹用来存放所有已安装到项目中的包。require()导入第三方包时,就是从这个目录中查找并加载包。</p>
<p>package-lock.json配置文件用来记录node_modules目录下的每一个包的下载信息,例如包的名字、版本号、下载地址等。</p>
<p>注意:不要手动修改node_modules或package-lock.json文件中的任何代码,npm包管理工具会自动维护它们。</p>
<h3>1.3.4、module对象</h3>
<p>在每个.js自定义模块中都有一个module对象,它里面存储了和当前模块有关的信息</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220906162201789-910642001.png" alt="" width="540" height="438" loading="lazy"></p>
<p>每个模块内部,module变量代表当前模块<br>module变量是一个对象,它的exports属性(即module.exports)是对外的接口<br>加载某个模块,其实是加载该模块的module.exports属性。require()方法用于加载模块。</p>
<h2>1.4、ESM与CJS</h2>
<p data-pid="dB96GB-a">学习 JavaScript 语言,你会发现它有两种格式的模块。一种是 ES6 模块,简称 ESM;另一种是 Node.js 专用的 CommonJS 模块,简称 CJS。这两种模块不兼容。</p>
<p data-pid="5igrMzR_">很多人使用 Node.js,只会用<code>require()</code>加载模块,遇到 ES6 模块就不知道该怎么办。本文就来谈谈,ES6 模块在 Node.js 里面怎么使用。</p>
<div>
<p><img src="https://img2023.cnblogs.com/blog/63651/202309/63651-20230911110617059-835344928.png" alt="" width="519" height="211" loading="lazy"></p>



</div>
<h3>1.4.1、两种模块的差异</h3>
<p data-pid="lw5cQg_s">ES6 模块和 CommonJS 模块有很大的差异。</p>
<p data-pid="rhNNEOFb">语法上面,CommonJS 模块使用<code>require()</code>加载和<code>module.exports</code>输出,ES6 模块使用<code>import</code>和<code>export</code>。</p>
<p data-pid="TAVM8ZRa">用法上面,<code>require()</code>是同步加载,后面的代码必须等待这个命令执行完,才会执行。<code>import</code>命令则是异步加载,或者更准确地说,ES6 模块有一个独立的静态解析阶段,依赖关系的分析是在那个阶段完成的,最底层的模块第一个执行。</p>
<h3>1.4.2、Node.js 的区分</h3>
<p data-pid="XS7w4VWh">Node.js 要求 ES6 模块采用<code>.mjs</code>后缀文件名。也就是说,只要脚本文件里面使用<code>import</code>或者<code>export</code>命令,那么就必须采用<code>.mjs</code>后缀名。Node.js 遇到<code>.mjs</code>文件,就认为它是 ES6 模块,默认启用严格模式,不必在每个模块文件顶部指定<code>"use strict"</code>。</p>
<p data-pid="_Nvui8CR">如果不希望将后缀名改成<code>.mjs</code>,可以在项目的<code>package.json</code>文件中,指定<code>type</code>字段为<code>module</code>。</p>
<div class="highlight">
<pre><code class="language-text">{
   "type": "module"
}</code></pre>
</div>
<p data-pid="-utDkaeP">一旦设置了以后,该目录里面的 JS 脚本,就被解释用 ES6 模块。</p>
<div class="highlight">
<pre><code class="language-text"># 解释成 ES6 模块
$ node my-app.js</code></pre>
</div>
<p data-pid="bA6cvd66">如果这时还要使用 CommonJS 模块,那么需要将 CommonJS 脚本的后缀名都改成<code>.cjs</code>。如果没有<code>type</code>字段,或者<code>type</code>字段为<code>commonjs</code>,则<code>.js</code>脚本会被解释成 CommonJS 模块。</p>
<p data-pid="34aQt-rH">总结为一句话:<code>.mjs</code>文件总是以 ES6 模块加载,<code>.cjs</code>文件总是以 CommonJS 模块加载,<code>.js</code>文件的加载取决于<code>package.json</code>里面<code>type</code>字段的设置。</p>
<p data-pid="ZYzxPHpG">注意,ES6 模块与 CommonJS 模块尽量不要混用。<code>require</code>命令不能加载<code>.mjs</code>文件,会报错,只有<code>import</code>命令才可以加载<code>.mjs</code>文件。反过来,<code>.mjs</code>文件里面也不能使用<code>require</code>命令,必须使用<code>import</code>。</p>
<p>ESM: es6 module规范及其实现; -----&gt; web统一的前端规范</p>
<p>  ES6 模块的设计思想是尽量的静态化,使得编译时就能确定模块的依赖关系,以及输入和输出的变量。</p>
<p>&nbsp; &nbsp; &nbsp; CommonJS 和 AMD 模块,都只能在运行时确定这些东西。</p>
<p>核心:</p>
<p>  独立作用域的</p>
<p>  export导出模块内数据&nbsp; &nbsp; &nbsp;---&gt; export</p>
<p>  import引入模块数据&nbsp; &nbsp; &nbsp; &nbsp;---&gt; 静态:import&nbsp; 只能放在文件开头&nbsp; &nbsp; &nbsp;引申:&nbsp; &nbsp;import()函数动态引入 ,返回 Module 对象</p>
<p>使用:</p>
<p>  &lt;script&nbsp; type = "module"&gt;</p>
<p>    // 这段代码 当做一个模块使用</p>
<p>  &lt;/script&gt;</p>
<p>  type = "module" 作用:</p>
<p>    声明这是一个模块</p>
<p>    具有独立的作用域</p>
<p>    使用 严格模式&nbsp; “use strict”</p>
<p>数据的导出: (es6 module 标准:web环境 和 nodejs环境 )</p>
<p>  export var a = 1;&nbsp; &nbsp; &nbsp;&lt;&lt;===========&gt;&gt;&nbsp; var a = 1; export { a };</p>
<p>  export var obj = { a:1 }&nbsp;&nbsp;&lt;&lt;===========&gt;&gt;&nbsp; var obj = { a:1 }; export { obj }</p>
<p>  export var funcName = function(){}&nbsp;&nbsp;&nbsp;&lt;&lt;===========&gt;&gt; var funcName = function(){}' export { funcName };</p>
<p>  -----------------------------------------------------&gt;&nbsp; export { 表达式 }</p>
<p>  导出多个:&nbsp; export { a, b, c, d}</p>
<p>  导出接口别名: export { a as s }&nbsp; &nbsp; &nbsp; s 是 a 的别名</p>
<p>  导出默认接口: export default&nbsp; &nbsp; -----&gt;&nbsp; &nbsp;export default&nbsp; var a = 1;</p>
<p>数据的引入:&nbsp;</p>
<p>   import&nbsp; &nbsp;先于模块内的其他模块执行( 会被js引擎静态分析)</p>
<p>  import variable from “文件路径”</p>
<p>  es6模块的实现是静态加载,import命令无法替代requrie的动态加载&nbsp; -----&gt; 提案中 引入了 import()&nbsp; 函数</p>
<p>  静态加载:&nbsp; import</p>
<p>       编译时加载</p>
<p>       只能在顶层结构中,否则报错 (编译错误,放在动态语句中报错,如 if语句)</p>
<p>       获取的是模块接口的引用</p>
<p>  动态加载: import()&nbsp; &nbsp;( 解决动态加载的问题)</p>
<p>       运行时加载</p>
<p>       import() 返回一个 Promise 对象</p>
<p>       模块、非模块脚本都可以加载</p>
<p>       导入的是一个 Module 对象, 当做 then 回调的参数</p>
<p>    btn.onclick = async function(){</p>
<p>      let cssModule = await &nbsp;import(“./m1.css”); &nbsp;//&nbsp;返回一个promise&nbsp;对象</p>
<p>      let css = cssModule.default;</p>
<p>    }</p>
<p>无关的补充:</p>
<p>  commonjs规范:一个文件是一个模块,module函数,每个文件都是module的实例;module.exports 数据的导出</p>
<p>  nodejs 的 require方法 是运行时加载的&nbsp;</p>
<p>  import命令无法替代 require的动态加载功能&nbsp; &nbsp;---&gt; import()来实现动态加载</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法一</span>
export <span style="color: rgba(0, 0, 255, 1)">var</span> m = 1<span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法二</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> m = 1<span style="color: rgba(0, 0, 0, 1)">; export { m };
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法三</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> n = 1<span style="color: rgba(0, 0, 0, 1)">; export { n as m };
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法四</span>
<span style="color: rgba(0, 0, 255, 1)">var</span> n = 1; export <span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> n;
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法五</span>
<span style="color: rgba(0, 0, 255, 1)">if</span> (<span style="color: rgba(0, 0, 255, 1)">true</span>) { import('./myModule.js').then(({ export1, export2 }) =&gt; { <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> ... </span><span style="color: rgba(0, 128, 0, 1)">*/</span><span style="color: rgba(0, 0, 0, 1)"> }); }
</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 写法六</span>
Promise.all([import('./module1.js'<span style="color: rgba(0, 0, 0, 1)">),
import(</span>'./module2.js'<span style="color: rgba(0, 0, 0, 1)">),
import(</span>'./module3.js')]).then(() =&gt; { <span style="color: rgba(0, 128, 0, 1)">/*</span><span style="color: rgba(0, 128, 0, 1)"> ... </span><span style="color: rgba(0, 128, 0, 1)">*/</span> });</pre>
</div>
<p>&nbsp;</p>
<h1>二、Node.js 文件系统</h1>
<p>Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:</p>
<pre><code>var fs = require("fs")
</code></pre>
<h2 id="异步和同步">2.1、异步和同步</h2>
<p>Node.js 文件系统(fs 模块)模块中的方法均有异步和同步版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。</p>
<p>异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。</p>
<p>建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。</p>
<p id="实例">实例</p>
<p>创建 input.txt 文件,内容如下:</p>
<pre><code>foo</code></pre>
<p>创建 filereaddemo.js 文件, 代码如下:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs");<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">依赖内置模块fs,用于文件管理</span>

<span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">异步读取文件students.txt,设置读取成功时的回调函数,err表示错误信息,data表示数据</span>
fs.readFile("students.txt",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err,data){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(err) <span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
    console.log(</span>"异步:"+data+""<span style="color: rgba(0, 0, 0, 1)">);
});

console.log(</span>"---------------"<span style="color: rgba(0, 0, 0, 1)">);

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)">同步读取</span>
let data=fs.readFileSync("students.txt"<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>"同步:"+data+"");</pre>
</div>
<p>以上代码执行结果如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907103649345-1026406307.png" alt="" width="606" height="133" loading="lazy"></p>
<p>接下来,让我们来具体了解下 Node.js 文件系统的方法。</p>
<h2 id="获取文件信息">2.2、获取文件信息</h2>
<p>以下为通过异步模式获取文件信息的语法格式:</p>
<pre><code>fs.stat(path, callback)</code></pre>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,带有两个参数如:(err, stats),&nbsp;stats&nbsp;是 fs.Stats 对象。</p>
</li>
</ul>
<p>fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs"<span style="color: rgba(0, 0, 0, 1)">);

fs.stat(</span>"students.txt",(err,stats)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    console.log(</span>"是文件吗?"+<span style="color: rgba(0, 0, 0, 1)">stats.isFile());
    console.log(</span>"是目录吗?"+<span style="color: rgba(0, 0, 0, 1)">stats.isDirectory());
    console.log(stats);
});</span></pre>
</div>
<p>结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907104336493-475550674.png" alt="" width="362" height="445" loading="lazy"></p>
<p>stats类中的方法有:</p>
<table>
<thead>
<tr><th>方法</th><th>描述</th></tr>
</thead>
<tbody>
<tr>
<td>stats.isFile()</td>
<td>如果是文件返回 true,否则返回 false。</td>
</tr>
<tr>
<td>stats.isDirectory()</td>
<td>如果是目录返回 true,否则返回 false。</td>
</tr>
<tr>
<td>stats.isBlockDevice()</td>
<td>如果是块设备返回 true,否则返回 false。</td>
</tr>
<tr>
<td>stats.isCharacterDevice()</td>
<td>如果是字符设备返回 true,否则返回 false。</td>
</tr>
<tr>
<td>stats.isSymbolicLink()</td>
<td>如果是软链接返回 true,否则返回 false。</td>
</tr>
<tr>
<td>stats.isFIFO()</td>
<td>如果是FIFO,返回true,否则返回 false。FIFO是UNIX中的一种特殊类型的命令管道。</td>
</tr>
<tr>
<td>stats.isSocket()</td>
<td>如果是 Socket 返回 true,否则返回 false。</td>
</tr>
</tbody>
</table>
<p id="实例">接下来我们创建 file.js 文件,代码如下所示:</p>
<pre><code>var fs = require("fs");

console.log("准备打开文件!");
fs.stat('input.txt', function (err, stats) {
   if (err) {
       return console.error(err);
   }
   console.log(stats);
   console.log("读取文件信息成功!");

   // 检测文件类型
   console.log("是否为文件(isFile) ? " + stats.isFile());
   console.log("是否为目录(isDirectory) ? " + stats.isDirectory());   
});
</code></pre>
<p>以上代码执行结果如下:</p>
<pre><code>$ node file.js
准备打开文件!
{ dev: 16777220,
mode: 33188,
nlink: 1,
uid: 501,
gid: 20,
rdev: 0,
blksize: 4096,
ino: 40333161,
size: 61,
blocks: 8,
atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST),
mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST),
ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) }
读取文件信息成功!
是否为文件(isFile) ? true
是否为目录(isDirectory) ? false
</code></pre>
<h2 id="写入文件">2.3、写入文件</h2>
<p>以下为异步模式下写入文件的语法格式:</p>
<pre><code>fs.writeFile(filename, data[, options], callback)
</code></pre>
<p>如果文件存在,该方法写入的内容会覆盖旧的文件内容。</p>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>data&nbsp;- 要写入文件的数据,可以是 String(字符串) 或 Buffer(流) 对象。</p>
</li>
<li>
<p>options&nbsp;- 该参数是一个对象,包含 {encoding, mode, flag}。默认编码为 utf8, 模式为 0666 , flag 为 'w'</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,回调函数只包含错误信息参数(err),在写入失败时返回。</p>
</li>
</ul>
<p>接下来我们创建 file.js 文件,代码如下所示:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs"<span style="color: rgba(0, 0, 0, 1)">);

fs.writeFile(</span>"output1.txt","异步hello","utf-8",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span>(!<span style="color: rgba(0, 0, 0, 1)">err){
      console.log(</span>"异步文件写入成功!"<span style="color: rgba(0, 0, 0, 1)">);
    }
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
      </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
    }
});
console.log(</span>"---------------"<span style="color: rgba(0, 0, 0, 1)">);
fs.writeFileSync(</span>"output2.txt","同步hello","utf-8"<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>"同步文件写入成功");</pre>
</div>
<p>以上代码执行结果如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907105510330-2070830305.png" alt="" width="495" height="118" loading="lazy"></p>
<span style="font-size: 1.5em">2.4、删除文件</span>
<p>以下为删除文件的语法格式:</p>
<pre><code>fs.unlink(path, callback)</code></pre>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,没有参数。</p>
</li>
</ul>
<p>接下来我们创建 file.js 文件,代码如下所示:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs"<span style="color: rgba(0, 0, 0, 1)">);

fs.unlink(</span>"output1.txt",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(err){
      </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
      console.log(</span>"异步删除文件成功!"<span style="color: rgba(0, 0, 0, 1)">);
    }
});
console.log(</span>"--------------------"<span style="color: rgba(0, 0, 0, 1)">);
fs.unlinkSync(</span>"output2.txt"<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>"同步删除文件成功!");</pre>
</div>
<p>以上代码执行结果如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907105954401-1469331183.png" alt="" width="546" height="102" loading="lazy"></p>
<h2>2.5、创建目录</h2>
<p>以下为创建目录的语法格式:</p>
<pre><code>fs.mkdir(path[, mode], callback)</code></pre>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>mode&nbsp;- 设置目录权限,默认为 0777。</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,没有参数。</p>
</li>
</ul>
<p>接下来我们创建mkdirfile.js 文件,代码如下所示:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs"<span style="color: rgba(0, 0, 0, 1)">);

fs.mkdir(</span>"dir1",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err){
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(err){
      </span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;
    }
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
      console.log(</span>"异步创建目录成功!"<span style="color: rgba(0, 0, 0, 1)">);
    }
});
console.log(</span>"---------------------"<span style="color: rgba(0, 0, 0, 1)">);
fs.mkdirSync(</span>"dir2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>"同步创建目录成功!");</pre>
</div>
<p>以上代码执行结果如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907110559489-1692484501.png" alt="" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<h2 id="读取目录">2.6、读取目录</h2>
<p>以下为读取目录的语法格式:</p>
<pre><code>fs.readdir(path, callback)</code></pre>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。</p>
</li>
</ul>
<p>接下来我们创建 file.js 文件,代码如下所示:</p>
<div class="cnblogs_code">
<pre>const fs=require("fs"<span style="color: rgba(0, 0, 0, 1)">);

fs.readdir(</span>"dir1",(err,files)=&gt;<span style="color: rgba(0, 0, 0, 1)">{
    </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)">(err)
    {</span><span style="color: rgba(0, 0, 255, 1)">throw</span><span style="color: rgba(0, 0, 0, 1)"> err;}
    </span><span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)">{
      console.log(</span>"异步获取目录下的文件成功!"<span style="color: rgba(0, 0, 0, 1)">);
      files.forEach(file</span>=&gt;<span style="color: rgba(0, 0, 0, 1)">console.log(file));
    }
});
console.log(</span>"-----------------------"<span style="color: rgba(0, 0, 0, 1)">);
let files</span>=fs.readdirSync("dir2"<span style="color: rgba(0, 0, 0, 1)">);
console.log(</span>"同步获取目录下的文件成功!"<span style="color: rgba(0, 0, 0, 1)">);
files.forEach(file</span>=&gt;console.log(file));</pre>
</div>
<p>以上代码执行结果如下:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907111332828-1141129546.png" alt="" loading="lazy"></p>
<h2 id="删除目录">2.7、删除目录</h2>
<p>以下为删除目录的语法格式:</p>
<pre><code>fs.rmdir(path, callback)</code></pre>
<p>参数使用说明如下:</p>
<ul>
<li>
<p>path&nbsp;- 文件路径。</p>
</li>
<li>
<p>callback&nbsp;- 回调函数,没有参数。</p>
</li>
</ul>
<p>接下来我们创建 file.js 文件,代码如下所示:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">var</span> fs = require("fs"<span style="color: rgba(0, 0, 0, 1)">);

console.log(</span>"准备删除目录 /tmp/test"<span style="color: rgba(0, 0, 0, 1)">);
fs.rmdir(</span>"/tmp/test",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err){
   </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
       </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> console.error(err);
   }
   console.log(</span>"读取 /tmp 目录"<span style="color: rgba(0, 0, 0, 1)">);
   fs.readdir(</span>"/tmp/",<span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)">(err, files){
      </span><span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (err) {
          </span><span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)"> console.error(err);
      }
      files.forEach( </span><span style="color: rgba(0, 0, 255, 1)">function</span><span style="color: rgba(0, 0, 0, 1)"> (file){
          console.log( file );
      });
   });
});</span></pre>
</div>
<p>以上代码执行结果如下:</p>
<pre><code>$ node file.js
准备删除目录 /tmp/test
input.out
output.out
test
test.txt
读取 /tmp 目录
……
</code></pre>
<h2 id="文件模块方法参考手册">2.8、文件模块方法参考手册</h2>
<p>以下为 Node.js 文件模块相同的方法列表:</p>
<table>
<thead>
<tr><th>方法</th><th>描述</th></tr>
</thead>
<tbody>
<tr>
<td>fs.rename(oldPath, newPath, callback)</td>
<td>异步 rename().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.ftruncate(fd, len, callback)</td>
<td>异步 ftruncate().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.ftruncateSync(fd, len)</td>
<td>同步 ftruncate()</td>
</tr>
<tr>
<td>fs.truncate(path, len, callback)</td>
<td>异步 truncate().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.truncateSync(path, len)</td>
<td>同步 truncate()</td>
</tr>
<tr>
<td>fs.chown(path, uid, gid, callback)</td>
<td>异步 chown().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.chownSync(path, uid, gid)</td>
<td>同步 chown()</td>
</tr>
<tr>
<td>fs.fchown(fd, uid, gid, callback)</td>
<td>异步 fchown().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.fchownSync(fd, uid, gid)</td>
<td>同步 fchown()</td>
</tr>
<tr>
<td>fs.lchown(path, uid, gid, callback)</td>
<td>异步 lchown().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.lchownSync(path, uid, gid)</td>
<td>同步 lchown()</td>
</tr>
<tr>
<td>fs.chmod(path, mode, callback)</td>
<td>异步 chmod().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.chmodSync(path, mode)</td>
<td>同步 chmod().</td>
</tr>
<tr>
<td>fs.fchmod(fd, mode, callback)</td>
<td>异步 fchmod().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.fchmodSync(fd, mode)</td>
<td>同步 fchmod().</td>
</tr>
<tr>
<td>fs.lchmod(path, mode, callback)</td>
<td>异步 lchmod().回调函数没有参数,但可能抛出异常。Only available on Mac OS X.</td>
</tr>
<tr>
<td>fs.lchmodSync(path, mode)</td>
<td>同步 lchmod().</td>
</tr>
<tr>
<td>fs.stat(path, callback)</td>
<td>异步 stat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。</td>
</tr>
<tr>
<td>fs.lstat(path, callback)</td>
<td>异步 lstat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。</td>
</tr>
<tr>
<td>fs.fstat(fd, callback)</td>
<td>异步 fstat(). 回调函数有两个参数 err, stats,stats 是 fs.Stats 对象。</td>
</tr>
<tr>
<td>fs.statSync(path)</td>
<td>同步 stat(). 返回 fs.Stats 的实例。</td>
</tr>
<tr>
<td>fs.lstatSync(path)</td>
<td>同步 lstat(). 返回 fs.Stats 的实例。</td>
</tr>
<tr>
<td>fs.fstatSync(fd)</td>
<td>同步 fstat(). 返回 fs.Stats 的实例。</td>
</tr>
<tr>
<td>fs.link(srcpath, dstpath, callback)</td>
<td>异步 link().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.linkSync(srcpath, dstpath)</td>
<td>同步 link().</td>
</tr>
<tr>
<td>fs.symlink(srcpath, dstpath[, type], callback)</td>
<td>异步 symlink().回调函数没有参数,但可能抛出异常。 type 参数可以设置为 'dir', 'file', 或 'junction' (默认为 'file') 。</td>
</tr>
<tr>
<td>fs.symlinkSync(srcpath, dstpath[, type])</td>
<td>同步 symlink().</td>
</tr>
<tr>
<td>fs.readlink(path, callback)</td>
<td>异步 readlink(). 回调函数有两个参数 err, linkString。</td>
</tr>
<tr>
<td>fs.realpath(path[, cache], callback)</td>
<td>异步 realpath(). 回调函数有两个参数 err, resolvedPath。</td>
</tr>
<tr>
<td>fs.realpathSync(path[, cache])</td>
<td>同步 realpath()。返回绝对路径。</td>
</tr>
<tr>
<td>fs.unlink(path, callback)</td>
<td>异步 unlink().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.unlinkSync(path)</td>
<td>同步 unlink().</td>
</tr>
<tr>
<td>fs.rmdir(path, callback)</td>
<td>异步 rmdir().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.rmdirSync(path)</td>
<td>同步 rmdir().</td>
</tr>
<tr>
<td>fs.mkdir(path[, mode], callback)</td>
<td>S异步 mkdir(2).回调函数没有参数,但可能抛出异常。 mode defaults to 0777.</td>
</tr>
<tr>
<td>fs.mkdirSync(path[, mode])</td>
<td>同步 mkdir().</td>
</tr>
<tr>
<td>fs.readdir(path, callback)</td>
<td>异步 readdir(3). 读取目录的内容。</td>
</tr>
<tr>
<td>fs.readdirSync(path)</td>
<td>同步 readdir().返回文件数组列表。</td>
</tr>
<tr>
<td>fs.close(fd, callback)</td>
<td>异步 close().回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.closeSync(fd)</td>
<td>同步 close().</td>
</tr>
<tr>
<td>fs.open(path, flags[, mode], callback)</td>
<td>异步打开文件。</td>
</tr>
<tr>
<td>fs.openSync(path, flags[, mode])</td>
<td>同步 version of fs.open().</td>
</tr>
<tr>
<td>fs.utimes(path, atime, mtime, callback)</td>
<td>?</td>
</tr>
<tr>
<td>fs.utimesSync(path, atime, mtime)</td>
<td>修改文件时间戳,文件通过指定的文件路径。</td>
</tr>
<tr>
<td>fs.futimes(fd, atime, mtime, callback)</td>
<td>?</td>
</tr>
<tr>
<td>fs.futimesSync(fd, atime, mtime)</td>
<td>修改文件时间戳,通过文件描述符指定。</td>
</tr>
<tr>
<td>fs.fsync(fd, callback)</td>
<td>异步 fsync.回调函数没有参数,但可能抛出异常。</td>
</tr>
<tr>
<td>fs.fsyncSync(fd)</td>
<td>同步 fsync.</td>
</tr>
<tr>
<td>fs.write(fd, buffer, offset, length[, position], callback)</td>
<td>将缓冲区内容写入到通过文件描述符指定的文件。</td>
</tr>
<tr>
<td>fs.write(fd, data[, position[, encoding]], callback)</td>
<td>通过文件描述符 fd 写入文件内容。</td>
</tr>
<tr>
<td>fs.writeSync(fd, buffer, offset, length[, position])</td>
<td>同步版的 fs.write()。</td>
</tr>
<tr>
<td>fs.writeSync(fd, data[, position[, encoding]])</td>
<td>同步版的 fs.write().</td>
</tr>
<tr>
<td>fs.read(fd, buffer, offset, length, position, callback)</td>
<td>通过文件描述符 fd 读取文件内容。</td>
</tr>
<tr>
<td>fs.readSync(fd, buffer, offset, length, position)</td>
<td>同步版的 fs.read.</td>
</tr>
<tr>
<td>fs.readFile(filename[, options], callback)</td>
<td>异步读取文件内容。</td>
</tr>
<tr>
<td>fs.readFileSync(filename[, options])</td>
<td>&nbsp;</td>
</tr>
<tr>
<td>fs.writeFile(filename, data[, options], callback)</td>
<td>异步写入文件内容。</td>
</tr>
<tr>
<td>fs.writeFileSync(filename, data[, options])</td>
<td>同步版的 fs.writeFile。</td>
</tr>
<tr>
<td>fs.appendFile(filename, data[, options], callback)</td>
<td>异步追加文件内容。</td>
</tr>
<tr>
<td>fs.appendFileSync(filename, data[, options])</td>
<td>The 同步 version of fs.appendFile.</td>
</tr>
<tr>
<td>fs.watchFile(filename[, options], listener)</td>
<td>查看文件的修改。</td>
</tr>
<tr>
<td>fs.unwatchFile(filename[, listener])</td>
<td>停止查看 filename 的修改。</td>
</tr>
<tr>
<td>fs.watch(filename[, options][, listener])</td>
<td>查看 filename 的修改,filename 可以是文件或目录。返回 fs.FSWatcher 对象。</td>
</tr>
<tr>
<td>fs.exists(path, callback)</td>
<td>检测给定的路径是否存在。</td>
</tr>
<tr>
<td>fs.existsSync(path)</td>
<td>同步版的 fs.exists.</td>
</tr>
<tr>
<td>fs.access(path[, mode], callback)</td>
<td>测试指定路径用户权限。</td>
</tr>
<tr>
<td>fs.accessSync(path[, mode])</td>
<td>同步版的 fs.access。</td>
</tr>
<tr>
<td>fs.createReadStream(path[, options])</td>
<td>返回ReadStream 对象。</td>
</tr>
<tr>
<td>fs.createWriteStream(path[, options])</td>
<td>返回 WriteStream 对象。</td>
</tr>
<tr>
<td>fs.symlink(srcpath, dstpath[, type], callback)</td>
<td>异步 symlink().回调函数没有参数,但可能抛出异常。</td>
</tr>
</tbody>
</table>
<p>更多内容,请查看官网文件模块描述:File System。</p>
<h1>三、参数与环境变量</h1>
<h2>3.0、读取自定义配置文件数据</h2>
<p>创立一个&nbsp;<code>config</code>&nbsp;目录并向其中增加一个&nbsp;<code>config/default.json</code>&nbsp;文件。这将是默认配置文件,并将蕴含所有默认环境变量。</p>
<p>在咱们的示例应用程序中它应该是这样的:</p>
<p>config/default.json</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
    </span>"student"<span style="color: rgba(0, 0, 0, 1)">:{
      </span>"name":"tom"<span style="color: rgba(0, 0, 0, 1)">,
      </span>"age":19<span style="color: rgba(0, 0, 0, 1)">
    }
}</span></pre>
</div>
<p>先依赖模块config,</p>
<div class="cnblogs_code">
<pre>npm i config</pre>
</div>
<p>咱们将在咱们的应用程序中通过导入&nbsp;<code>config</code>&nbsp;和应用&nbsp;<code>get</code>&nbsp;办法拜访变量来访问它。</p>
<div class="cnblogs_code">
<pre>const config=require("config"<span style="color: rgba(0, 0, 0, 1)">);
console.log(config.get(</span>"student.name"<span style="color: rgba(0, 0, 0, 1)">));
console.log(config.get(</span>"student.age"));</pre>
</div>
<p>运行结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908110509811-1031529060.png" alt="" width="438" height="81" loading="lazy"></p>
<h2>3.1、读取package.json配置参数</h2>
<p>用于添加命令行的环境变量</p>
<p>package.json 可以配置config<br>脚本中 (see npm-scripts) package.json “config” 字段会被环境变量覆盖<br>&lt;name&gt;[@&lt;version&gt;]:&lt;key&gt;<br>例如,下面的package.json:<br>代码中使用 process.env['npm_package_config_xxxxxx'] 获取配置的内容</p>
<p>package.json</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span>"name": "demo06"<span style="color: rgba(0, 0, 0, 1)">,
</span>"config"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"foo": "123456"<span style="color: rgba(0, 0, 0, 1)">
},
</span>"version": "1.0.0"<span style="color: rgba(0, 0, 0, 1)">,
</span>"description": ""<span style="color: rgba(0, 0, 0, 1)">,
</span>"main": "index.js"<span style="color: rgba(0, 0, 0, 1)">,
</span>"scripts"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"test": "echo \"Error: no test specified\" &amp;&amp; exit 1"<span style="color: rgba(0, 0, 0, 1)">,
    </span>"start":"node configtest.js"<span style="color: rgba(0, 0, 0, 1)">
},
</span>"keywords"<span style="color: rgba(0, 0, 0, 1)">: [],
</span>"author": ""<span style="color: rgba(0, 0, 0, 1)">,
</span>"license": "ISC"<span style="color: rgba(0, 0, 0, 1)">,
</span>"dependencies"<span style="color: rgba(0, 0, 0, 1)">: {
    </span>"config": "^3.3.7"<span style="color: rgba(0, 0, 0, 1)">
}
}</span></pre>
</div>
<p>configtest.js</p>
<div class="cnblogs_code">
<pre>console.log(process.env.npm_package_config_foo);</pre>
</div>
<p>直接运行(node configtest.js)结果:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908105400918-1895669324.png" alt="" width="708" height="89" loading="lazy"></p>
<p><span style="color: rgba(255, 0, 0, 1)">直接在命令行执行 node configtest,会输出undefined</span></p>
<p>使用 npm run start,会输出 123456</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908105445603-855481403.png" alt="" width="386" height="119" loading="lazy"></p>
<p>npm 设置包的config</p>
<p>npm config set foo = 3000 就可以修改默认的配置内容</p>
<p>然后再执行 npm test 会输出 3000</p>
<h2>3.2、环境变量的设置与读取</h2>
<p>文件.env</p>
<div class="cnblogs_code">
<pre>USER_ID="239482"<span style="color: rgba(0, 0, 0, 1)">
USER_KEY</span>="foobar"<span style="color: rgba(0, 0, 0, 1)">
NODE_ENV</span>="development"</pre>
</div>
<p>m3.js</p>
<p>&nbsp;npm i dotenv&nbsp; //依赖模块</p>
<div class="cnblogs_code">
<pre>require("dotenv"<span style="color: rgba(0, 0, 0, 1)">).config();
console.log(process.env.USER_ID);</span></pre>
</div>
<p>输出结果:</p>
<div>239482</div>
<div><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908110958123-1911537520.png" alt="" width="760" height="303" loading="lazy"></div>
<div>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">在Node.js中使用dotenv库可以帮助你管理不同环境的配置。你可以为不同的环境创建不同的.env文件,并在这些文件中设置环境变量。然后,你可以在应用程序启动时加载这些环境变量。

以下是如何使用dotenv来切换环境的步骤:

安装dotenv库:

npm install dotenv

在项目根目录下创建不同的.env文件,例如:.env.development,.env.test,.env.production。

在.env文件中设置环境变量,例如:

.env.development:

DB_HOST</span>=<span style="color: rgba(0, 0, 0, 1)">localhost
DB_USER</span>=<span style="color: rgba(0, 0, 0, 1)">dev_user
DB_PASS</span>=<span style="color: rgba(0, 0, 0, 1)">dev_password

.env.production:

DB_HOST</span>=<span style="color: rgba(0, 0, 0, 1)">production_host
DB_USER</span>=<span style="color: rgba(0, 0, 0, 1)">prod_user
DB_PASS</span>=<span style="color: rgba(0, 0, 0, 1)">prod_password

在你的Node.js应用程序中使用dotenv来加载对应的.env文件:

</span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 在应用程序的入口文件或启动脚本中</span>
require('dotenv').config({ path: '.env.development' }); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 开发环境</span><span style="color: rgba(0, 128, 0, 1)">
//</span><span style="color: rgba(0, 128, 0, 1)"> 或者</span>
require('dotenv').config({ path: '.env.production' }); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 生产环境</span>
<span style="color: rgba(0, 0, 0, 1)">
使用process.env访问环境变量:

console.log(process.env.DB_HOST); </span><span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 输出数据库主机地址</span>
<span style="color: rgba(0, 0, 0, 1)">
确保在你的部署脚本或配置中指定正确的环境变量文件,以便在不同环境之间切换时,应用程序能够使用正确的配置。</span></pre>
</div>
</div>
<h2>3.3、获取系统中的环境变量</h2>
<p>命令行下操作环境变量</p>
<h3>3.3.1、查看当前所有可用的环境变量</h3>
<p>输入 set 即可查看。</p>
<p><img src="https://zsrimg.ikafan.com/file_images/article/202206/20220602162916144.png"></p>
<h3>3.3.2、查看某个环境变量</h3>
<p>输入 “set 变量名”即可。比如想查看path变量的值,即输入 set path</p>
<p><img src="https://zsrimg.ikafan.com/file_images/article/202206/20220602162916145.png"></p>
<h3>3.3.3、修改环境变量</h3>
<p>注意:所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改。也就是说当关闭此cmd命令行窗口后,将不再起作用。</p>
<p>永久性修改环境变量的方法有两种:一种是直接修改注册表,另一种是通过我的电脑-〉属性-〉高级,来设置系统的环境变量(查看详细)。</p>
<h4>1、修改环境变量</h4>
<p>输入 “set 变量名=变量内容”即可。比如将path设置为“d:\nmake.exe”,只要输入set path="d:\nmake.exe"。</p>
<p>注意,此修改环境变量是指用现在的内容去覆盖以前的内容,并不是追加。比如当我设置了上面的path路径之后,如果我再重新输入set path="c",再次查看path路径的时候,其值为“c:”,而不是“d:\nmake.exe”;“c”。</p>
<h4>2、设置为空:</h4>
<p>如果想将某一变量设置为空,输入“set 变量名=”即可。</p>
<p>如“set path=” 那么查看path的时候就为空。注意,上面已经说了,只在当前命令行窗口起作用。因此查看path的时候不要去右击“我的电脑”——“属性”........</p>
<h4>3、给变量追加内容</h4>
<p>输入“set 变量名=%变量名%;变量内容”。(不同于3,那个是覆盖)。如,为path添加一个新的路径,输入“ set path=%path%;d:\nmake.exe”即可将d:\nmake.exe添加到path中,再次执行"set path=%path%;c:",那么,使用set path语句来查看的时候,将会有:d:\nmake.exe;c:,而不是像第3步中的只有c:。</p>
<h3>3.3.4、一些常用的环境变量</h3>
<ul>
<li>%AllUsersProfile%: 局部 返回所有“用户配置文件”的位置。 {所有用户文件目录 – C:\Documents and Settings\All Users}</li>
<li>%AppData%: 局部 返回默认情况下应用程序存储数据的位置。 {当前用户数据文件夹 – C:\Documents and Settings\wy\Application Data}</li>
<li>%Cd%: 局部 返回当前目录字符串。</li>
<li>%CmdCmdLine%: 局部 返回用来启动当前的 Cmd.exe 的准确命令行。</li>
<li>%CmdExtVersion%: 系统 返回当前的“命令处理程序扩展”的版本号。</li>
<li>%CommonProgramFiles%: {文件通用目录 – C:\Program Files\Common Files}</li>
<li>%ComputerName%: 系统 返回计算机的名称。 {计算机名 – IBM-B63851E95C9}</li>
<li>%ComSpec%: 系统 返回命令行解释器可执行程序的准确路径。 C:\WINDOWS\system32\cmd.exe</li>
<li>%Date%: 系统 返回当前日期。使用与 date /t 命令相同的格式。由 Cmd.exe 生成。有关 date 命令的详细信息,请参阅 Date。</li>
<li>%ErrorLevel%: 系统 返回最近使用过的命令的错误代码。通常用非零值表示错误。</li>
<li>%HomeDrive%: 系统 返回连接到用户主目录的本地工作站驱动器号。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。 {当前用户根目录 – C:}</li>
<li>%HomePath%: 系统 返回用户主目录的完整路径。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。 {当前用户路径 – \Documents and Settings\wy}</li>
<li>%HomeShare%: 系统 返回用户的共享主目录的网络路径。基于主目录值的设置。用户主目录是在“本地用户和组”中指定的。</li>
<li>%LogonSever%: 局部 返回验证当前登录会话的域控制器的名称。</li>
<li>%Number_Of_Processors%: 系统 指定安装在计算机上的处理器的数目。 {处理器个数 – 1}</li>
<li>%Os%: 系统 返回操作系统的名称。Windows 2000 将操作系统显示为 Windows_NT。 {操作系统名 – Windows_NT}</li>
<li>%Path%: 系统 指定可执行文件的搜索路径。</li>
<li>%PathExt%: 系统 返回操作系统认为可执行的文件扩展名的列表。</li>
<li>%Processor_Architecture%: 系统 返回处理器的芯片体系结构。值: x86,IA64。 {处理器芯片架构 – x86}</li>
<li>%Processor_Identfier%: 系统 返回处理器说明。</li>
<li>%Processor_Level%: 系统 返回计算机上安装的处理器的型号。 {处理器型号 – 6}</li>
<li>%Processor_Revision%: 系统 返回处理器修订号的系统变量。 {处理器修订号 – 0905}</li>
<li>%ProgramFiles%: {程序默认安装目录 – C:\Program Files}</li>
<li>%Prompt%: 局部 返回当前解释程序的命令提示符设置。由 Cmd.exe 生成。 $P$G</li>
<li>%Random%: 系统 返回 0 到 32767 之间的任意十进制数字。由 Cmd.exe 生成。</li>
<li>%SystemDrive%: 系统 返回包含 Windows XP 根目录(即系统根目录)的驱动器。 {系统根目录 – C:}</li>
<li>%SystemRoot%: 系统 返回 Windows XP 根目录的位置。 {系统目录 – C:\WINDOWS}</li>
<li>%Temp%: 系统和用户 返回对当前登录用户可用的应用程序所使用的默认临时目录。有些应用程序需要 TEMP,而其它应用程序则需要 TMP。 {当前用户临时文件夹 – C:\DOCUME~1\wy\LOCALS~1\Temp}</li>
<li>%Time%: 系统 返回当前时间。使用与 time /t 命令相同的格式。由 Cmd.exe 生成。9:16:25.05</li>
<li>%UserDomain%: 局部 返回包含用户帐户的域的名称。 {包含用户帐号的域 – IBM-B63851E95C9}</li>
<li>%UserName%: 局部 返回当前登录的用户的名称。 {当前用户名 – wy}</li>
<li>%UserProfile%: 局部 返回当前用户的配置文件的位置。 {当前用户目录 – C:\Documents and Settings\wy}</li>
<li>%WinDir%: 系统 返回操作系统目录的位置。 {系统目录 – C:\WINDOWS}</li>
</ul>
<p>假定当前的系统环境变量定义如下,注意JAVA_HOME:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907153911771-1488110985.png" alt="" loading="lazy"></p>
<p>&nbsp;m3.js</p>
<div class="cnblogs_code">
<pre>console.log(process.env.JAVA_HOME);</pre>
</div>
<p>输出:</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220907154003656-433144588.png" alt="" width="471" height="71" loading="lazy"></p>
<p>&nbsp;<img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908115021458-603212853.png" alt="" loading="lazy"></p>
<p>a,b在系统中已定义好</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908145217797-367135745.png" alt="" loading="lazy"></p>
<p>注意当前的终端是cmd,不是powershell</p>
<p><img src="https://img2022.cnblogs.com/blog/63651/202209/63651-20220908145137246-278933297.png" alt="" width="918" height="570" loading="lazy"></p>
<p>&nbsp;</p>
<p>&nbsp;这里a输出123的原因是修改成888后没有重启电脑。</p>
<h3>3.3.5、设置永久环境变量</h3>
<p><strong>set命令</strong></p>
<p>set命令用于设置当前cmd窗口中的环境变量,只在当前cmd窗口有效,cmd窗口关闭后将会失效,而其不会影响到系统中保存的用户环境变量。</p>
<p>&nbsp;</p>
<p><strong>setx命令</strong><br>setx设置永久用户环境变量</p>
<blockquote>
<p>setx env_name env_value</p>



</blockquote>
<p>注意:有的路径中会带有空格,所以最好用双引号把变量和值都包裹起来,也就是写成如下形式:</p>
<blockquote>
<p>setx "env_name" "env_value"</p>



</blockquote>
<p>例,追加一个路径到用户path环境变量中:</p>
<blockquote>
<p>setx "path" "D:\test;%path%"</p>



</blockquote>
<p><strong>setx设置永久系统环境变量</strong></p>
<p>setx加上/m参数表示设置的是系统的环境变量,格式如下所示:</p>
<blockquote>
<p>setx env_name env_value /m</p>



</blockquote>
<p>注意:有的路径中会带有空格,所以最好用双引号把变量和值都包裹起来,也就是写成如下形式:</p>
<blockquote>
<p>setx "env_name" "env_value" /m</p>



</blockquote>
<p>例如,设置当前路径%cd%到系统环境环境变量中:</p>
<blockquote>
<p>setx "Path" "%cd%;%path%" /m</p>



</blockquote>
<p>注意:setx设置环境变量后,将在新打开的终端中生效,当前终端不会立即生效。<br>注意:setx可能会在环境变量中设置多个相同的值,例如,在当前cmd窗口中运行:</p>
<blockquote>
<p>setx "Path" "D:\test;%path%" /m</p>



</blockquote>
<p>然后再重新打开cmd窗口,进入D:\test路径,然后再次运行:</p>
<blockquote>
<p>setx "Path" "D:\test;%path%" /m</p>



</blockquote>
<p>这样D:\test将会在path环境变量中出现两次.</p>
<h4>用setx设置永久环境变量及注意事项</h4>
<p>设置用户环境变量</p>
<blockquote>
<p>setx ENV_NAME env_value</p>



</blockquote>
<p>设置系统环境变量</p>
<blockquote>
<p>setx ENV_NAME env_value /m</p>



</blockquote>
<p>注意1.<br>在某些情况下会出现“setx 无效语法 默认选项不能超过'2'次”的错误,据信是因为原先的环境变量中存在空格导致的,可使用双引号进行避免。</p>
<p>注意2.</p>
<p>setx设置环境变量后,将在新打开的终端中生效,当前终端不会立即生效。所以当设置path这样内容较为丰富的环境变量时,要一次到位,而不要针对同一变量反复调用setx。例如:</p>
<p>正确做法:</p>
<blockquote>
<p>set path_=%Path%<br>setx “Path” “%path_%;newpath1;newpath2” /m</p>



</blockquote>
<p>错误做法:</p>
<blockquote>
<p>set path_=%Path%<br>setx “Path” “%path_%;newpath1” /m<br>setx “Path” “%path_%;newpath2” /m</p>



</blockquote>
<p>上述错误的做法将会漏掉newpath1。</p>
<h1>四、作业</h1>
<p>4.1、根据视频完成每一个上课示例。</p>
<p>4.2、定义一个模块circle.js,中模块中定义两个方法一个用于计算圆的周长,一个用于计算圆的面积,再定义一个模块main.js依赖模块circle.js,并调用模块中的两个方法用于计算。</p>
<p>分别使用CJS与ESM完成。</p>
<p>4.3、在配置文件package.json中定义好端口port与主机地址host,创建一个web服务器,引用配置信息,实现端口与主机地址的切换功能。</p>
<p>4.4、使用config的方式完成4.3</p>
<p>4.5、使用.env,dotenv的方式完成4.3</p>
<p>4.6、使用系统环境变量完成4.3</p>
<h1>&nbsp;五、视频</h1>
<p>https://www.bilibili.com/video/BV1WW411B78S</p>
<p>&nbsp;</p><br><br>
来源:https://www.cnblogs.com/best/p/16418465.html
頁: [1]
查看完整版本: Node.js学习笔记(二)——Node.js模块化、文件读写、环境变量