Node.js的学习(二)node.js 模块化

一、Node.js模块化

 1、模块化概要

早期的javascript版本没有块级作用域、没有类、没有包、也没有模块,这样会带来一些问题,如复用、依赖、冲突、代码组织混乱等,随着前端的膨胀,模块化显得非常迫切。

通俗点来说:模块化就是把手机变成一个一个零件,可以拼装,哪个零件坏了可以换,就不用整个手机都需要换,就像搭积木一样

 前端模块化规范如下:

 常见的的JavaScript模块规范有:CommonJS、AMD、CMD、UMD、原生模块化(ES6的时候有学)

模块化是指解决一个复杂问题时,自顶向下逐层把系统划分成若干模块的过程。对于整个系统来说,模块是可组合、分解和更换 的单元

JavaScript在早期的设计中就没有模块、包、类的概念,开发者需要模拟出类似的功能,来隔离、组织复杂的JavaScript代码,我们称为模块化。

模块就是一个实现特定功能的文件,有了模块我们就可以更方便的使用别人的代码,要用什么功能就加载什么模块。

2、模块化开发的四点好处:

  (1)、避免变量污染,命名冲突

  (2)、提高代码复用率

  (3)、提高了可维护性

  (4)、方便依赖关系管理

nodejs 中根据模块的来源不同,将模块分为了3大类,分别是:

  • 内置模块(内置模块是由Node.js官方提供的,例如fs、path、http等)
  • 自定义模块 (用户创建的每个 .js文件,都是自定义模块)
  • 第三方模块 (由第三方开发出来的模块,并非官方提供的内置模块,也不是用户创建的自定义模块,使用前需要先下载)

3、模块作用域

和函数作用域类似,在自定义模块中定义的变量、方法等成员,只能在当前模块内被访问,这种模块级别的访问限制,叫做模块作用域。

模块作用域的好处:防止了全局变量污染的问题

4、变量作用域

(1)、在浏览器端使用var或不使用关键字定义的变量属于全局作用域,也就是可以使用window对象访问。

<script>
      var a = 100;

      (function () {
        b = 200;
      })();

      console.log(window.a, a);
      console.log(window.b, b);
</script>

结果:

 (2)、在 Node.js 中没有 window 对象

  (3)、在Node.js的交互环境下,定义的变量属于global,global是类似浏览器端的window对象

  (4)、在模块中(文件中)有global对象,使用关键字var,let,const定义的成员不属于global对象,仅在当前模块中有效,而不使用关键字定义的对象属于global对象。

var a=100;
b=200;
let c=300;
const d=400;
console.log(global);
console.log(global.a);
console.log(global.b);
console.log(global.c);
console.log(global.d);

终端输出:

5、CommonJS

CommonJS就是一个JavaScript模块化的规范,该规范最初是用在服务器端 NodeJS 中,前端的 webpack 也是对CommonJS原生支持的。

根据这个规范

(1)、每一个文件就是一个模块,其内部定义的变量是属于这个模块的,不会对外暴露,也就是说不会污染全局变量。

(2)、导入自定义的模块时路径需要以 ./ 或 ../ 开始,同一路径下也不能省略。

(3)、如果反复多次require模块,只加载一次。

(4)、require引入模块时,后缀名.js可以省略

(5)、每个模块文件都是一个独立的函数级作用域,在其它模块中不能直接访问

  举个栗子:

  m1.js 文件代码:

console.log("这是模块m1");
let a=100;
b=200;

  m2.js 文件代码: 

var m11=require("./m1");
console.log(a);
console.log(b);

  结果:

  

 从上面的示例可以看出a在模块2中是访问不到的,模块其实就是一个封闭的函数:

m1.js 文件的代码:

console.log("这是模块m1");
let a=100;
b=200;
//输出当前函数
console.log(arguments.callee+"");

输出结果:

 (6)、每个模块中都包含如下5个对象:

exports:导出对象,默认为{}

 require:导入函数,使用该函数可以实现模块的依赖

 module:模块信息,用于记录当前模块的所有信息

 __filename:当前模块的文件全路径,含文件名

 __dirname:当前模块的文件路径,不含文件名

 (7)、使用exports或module.exports对象可以将当前模块中需要导出的内容暴露出去。

 m4.js 文件代码:

let a=100;
let b=()=>{
return 200;
};

exports.a=a;
exports.b=b; 

m5.js 文件代码:

const m1=require("./m1");
console.log(m1);
console.log(m1.a);
console.log(m1.b());

运行结果:

 (8)、导入模块内容可以结合结构语法

m6.js 文件代码:

exports.a=100;
exports.b=function(){
    return 200;
};

m7.js 文件代码:

const {a,b:fun}=require("./m6");// 模块结合解构
console.log(a);
console.log(fun());

运行结果:

 二、Node.js 文件系统

2.1、概要

Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。 Node 导入文件系统模块(fs)语法如下所示:

var fs = require("fs")

2.3、异步与同步

Node.js 文件系统(fs 模块)模块中的方法均有 异步和同步 版本,例如读取文件内容的函数有异步的 fs.readFile() 和同步的 fs.readFileSync()。

异步的方法函数最后一个参数为回调函数,回调函数的第一个参数包含了错误信息(error)。

建议大家是用异步方法,比起同步,异步方法性能更高,速度更快,而且没有阻塞。

实例

创建 input.txt 文件,内容如下:

foo

创建 filereaddemo.js 文件, 代码如下:

const fs=require("fs");  //依赖内置模块fs,用于文件管理

//异步读取文件index.txt,设置读取成功时的回调函数,err表示错误信息,data表示数据
fs.readFile("index.txt",function(err,data){
    if(err) throw err; // 抛出异常
    console.log("异步:"+data+"");
});

console.log("---------------");

//同步读取
let data=fs.readFileSync("index.txt");
console.log("同步:"+data+"");

运行结果:

注意:异步完成时间是不确定的,一般异步完成时间最慢!!!

2.2、写入文件

创建 file.js 文件,代码如下所示:

const fs=require("fs");

// 异步写入文件
fs.writeFile("output1.txt","异步hello","utf-8",function(err){
    if(!err){
        console.log("异步文件写入成功!");
    }
    else{
        throw err;
    }
});
console.log("---------------");

// 同步写入文件
fs.writeFileSync("output2.txt","同步hello","utf-8");
console.log("同步文件写入成功");

运行结果:

 

 

2.3、获取文件信息

以下为通过异步模式获取文件信息的语法格式:

fs.stat(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,带有两个参数如:(err, stats), stats 是 fs.Stats 对象。

fs.stat(path)执行后,会将stats类的实例返回给其回调函数。可以通过stats类中的提供方法判断文件的相关属性。例如判断是否为文件:

创建一个 isfile 文件,代码如下:

// 判断是否为文件:
const fs=require("fs");

// 获取文件信息
fs.stat("student.txt",(err,stats)=>{
    console.log("是文件吗?"+stats.isFile());
    console.log("是目录吗?"+stats.isDirectory());
    console.log(stats);
});

运行结果:

 stats类中的方法有:

 2.4、删除文件

以下为删除文件的语法格式:

fs.unlink(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,没有参数。

创建 deleteFile.js 文件,代码如下:

const fs=require("fs");

fs.unlink("output1.txt",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("异步删除文件成功!");
    }
});
console.log("--------------------");
fs.unlinkSync("output2.txt");
console.log("同步删除文件成功!");

运行结果:

 2.5、创建目录

以下为创建目录的语法格式:

fs.mkdir(path[, mode], callback)

参数使用说明如下:

  • path - 文件路径。

  • mode - 设置目录权限,默认为 0777。

  • callback - 回调函数,没有参数。

创建mkdirfile.js 文件,代码如下所示:

const fs=require("fs");

fs.mkdir("dir1",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("异步创建目录成功!");
    }
});
console.log("---------------------");
fs.mkdirSync("dir2");
console.log("同步创建目录成功!");

运行结果:

 

2.6、读取目录

以下为读取目录的语法格式:

fs.readdir(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,回调函数带有两个参数err, files,err 为错误信息,files 为 目录下的文件数组列表。

创建 readDirectory.js 文件,代码如下:

// 读取目录
const fs=require("fs");

// 异步
fs.readdir("dir1",(err,files)=>{
    if(err) 
    {throw err;}
    else{
        console.log("异步获取目录下的文件成功!");
        files.forEach(file=>console.log(file));
    }
});
console.log("-----------------------");

// 同步
let files=fs.readdirSync("dir2");
console.log("同步获取目录下的文件成功!");
files.forEach(file=>console.log(file));

运行结果:

 

 2.7、删除空目录

以下为删除空目录的语法格式:

fs.rmdir(path, callback)

参数使用说明如下:

  • path - 文件路径。

  • callback - 回调函数,没有参数。

接下来我们创建 delDirectory.js 文件,代码如下所示:

var fs = require("fs");

// 异步删除
fs.rmdir("dir1",function(err){
    if(err){
        throw err;
    }
    else{
        console.log("异步删除目录成功");
    }   
});

console.log("=================================");

// 同步删除
// recursive:递归删除
fs.rmdirSync("dir2");
console.log("同步删除目录成功");

运行结果:

 2.8、删除非空目录

以下为删除非空目录的语法格式:

fs.rm(path,callback);

创建一个delDirectory2.js 文件,代码如下:

var fs = require("fs");
 
// 异步删除非空目录
fs.rm("dir1",{recursive: true},err=>{
    if (err) {
        throw err;
    }
    console.log("异步删除非空目录成功!");
});

运行结果:

 三、参数与环境变量

3.1、读取package.json文件配置参数

创立一个 config 目录并向其中增加一个 config/default.json 文件。这将是默认配置文件,并将蕴含所有默认环境变量

获取配置的内容:

process.env['npm_package_config_xxxxxx'] 

在咱们的示例应用程序中它应该是这样的:

package.json 文件中,新添加一个 “ config ” ,然后设置一些自定义的参数:

 然后新建一个config.js 文件,代码如下:

console.log(process.env.npm_package_config_foo);

请注意:要是直接运行,它的值为:undefined,如何解决?解决方法如下:

(1)在package.json文件中的 scripts中添加一行 “ start ”:node 要运行的文件名

 (2)在终端哪里,输入命令:npm run start  回车,即可解决

3.2、读取自定义配置文件数据

首先创建一个 default.json 文件,代码如下:

{
   "student":{
        "name":"tom",
        "age":"18"
   } 
}

先依赖模块config,命令如下:

npm i config

咱们将在咱们的应用程序中通过导入 config 和应用 get 办法拜访变量来访问它,代码如下:

const config = require("config");

console.log(config);
console.log(config.get("student.name"));
console.log(config.get("student.age"));

运行结果:

3.3、使用evn、dotenv依赖读取参数

(1)首先导入依赖

npm i dotenv  //依赖模块

(2)自定义创建 .env 文件代码如下:

USER_ID="239482"
USER_KEY="foobar"
NODE_ENV="development"

(3)自定义创建 env.js 文件代码如下:

require("dotenv").config();
console.log(process.env.USER_ID);

运行结果:

 

3.4、环境变量的设置与读取

3.4.1、查看当前所有可用的环境变量

命令如下:

set

 3.4.2、查看某个环境变量

命令如下:

set 变量名

具体操作步骤如下:

首先在电脑上的属性 -> 高级系统设置中,新添加一个环境变量

 请注意:在环境变量中添加或修改了变量,需要启电脑!!!

运行结果如下:

3.4.3、修改环境变量

请注意:所有的在cmd命令行下对环境变量的修改只对当前窗口有效,不是永久性的修改。也就是说当关闭此cmd命令行窗口后,将不再起作用。

修改环境变量命令如下:

set 变量名=变量内容

运行结果:

 请注意,此修改环境变量是指用现在的内容去覆盖以前的内容

 3.4.4、修改环境变量为空

命令如下:

"set 变量名="

3.4.5、给变量追加内容

命令如下:

“set 变量名=%变量名%;变量内容”

3.4.6、修改环境变量的值并访问

命令如下:

set a=900 && node envcfg.js

运行结果如下:

  

 

posted @ 2022-09-12 19:51  __fairy  阅读(293)  评论(0编辑  收藏  举报